@@ -177,9 +177,9 @@ proxy :: Serializable a => ProcessId -> (a -> Process Bool) -> Process ()
177
177
{% endhighlight %}
178
178
179
179
Since ` matchAny ` operates on ` (Message -> Process b) ` and ` handleMessage ` operates on
180
- ` a -> Process b ` we can compose these to make our proxy server. We must not forward
180
+ ` a -> Process b ` we can compose these to make our proxy server. We must not forward
181
181
messages for which the predicate function evaluates to ` Just False ` , nor can we sensibly
182
- forward messages which the predicate function is unable to evaluate due to type
182
+ forward messages which the predicate function is unable to evaluate due to type
183
183
incompatibility. This leaves us with the definition found in distributed-process:
184
184
185
185
{% highlight haskell %}
@@ -197,7 +197,7 @@ proxy pid proc = do
197
197
198
198
Beyond simple relays and proxies, the raw message handling capabilities available in
199
199
distributed-process can be utilised to develop highly generic message processing code.
200
- All the richness of the distributed-process-platform APIs (such as ` ManagedProcess ` ) which
200
+ All the richness of the distributed-process-client-server APIs (such as ` ManagedProcess ` ) which
201
201
will be discussed in later tutorials are, in fact, built upon these families of primitives.
202
202
203
203
### Typed Channels
@@ -234,10 +234,10 @@ is terminated.
234
234
235
235
The ` ProcessExitException ` signal is sent from one process to another, indicating that the
236
236
receiver is being asked to terminate. A process can choose to tell itself to exit, and the
237
- [ ` die ` ] [ 7 ] primitive simplifies doing so without worrying about the expected type for the
237
+ [ ` die ` ] [ 7 ] primitive simplifies doing so without worrying about the expected type for the
238
238
action. In fact, [ ` die ` ] [ 7 ] has slightly different semantics from [ ` exit ` ] [ 5 ] , since the
239
239
latter involves sending an internal signal to the local node controller. A direct consequence
240
- of this is that the _ exit signal_ may not arrive immediately, since the _ Node Controller_ could
240
+ of this is that the _ exit signal_ may not arrive immediately, since the _ Node Controller_ could
241
241
be busy processing other events. On the other hand, the [ ` die ` ] [ 7 ] primitive throws a
242
242
` ProcessExitException ` directly in the calling thread, thus terminating it without delay.
243
243
In practise, this means the following two functions could behave quite differently at
@@ -247,19 +247,19 @@ runtime:
247
247
248
248
-- this will never print anything...
249
249
demo1 = die "Boom" >> expect >>= say
250
-
250
+
251
251
-- this /might/ print something before it exits
252
252
demo2 = do
253
253
self <- getSelfPid
254
254
exit self "Boom"
255
- expect >>= say
255
+ expect >>= say
256
256
{% endhighlight %}
257
257
258
258
The ` ProcessExitException ` type holds a _ reason_ field, which is serialised as a raw ` Message ` .
259
259
This exception type is exported, so it is possible to catch these _ exit signals_ and decide how
260
260
to respond to them. Catching _ exit signals_ is done via a set of primitives in
261
261
distributed-process, and the use of them forms a key component of the various fault tolerance
262
- strategies provided by distributed-process-platform .
262
+ strategies provided by distributed-process-supervisor .
263
263
264
264
A ` ProcessKillException ` is intended to be an _ untrappable_ exit signal, so its type is
265
265
not exported and therefore you can __ only__ handle it by catching all exceptions, which
@@ -296,7 +296,7 @@ special case. Since link exit signals cannot be caught directly, if you find you
296
296
to _ trap_ a link failure, you probably want to use a monitor instead.
297
297
298
298
Whilst the built-in ` link ` primitive terminates the link-ee regardless of exit reason,
299
- distributed-process-platform provides an alternate function ` linkOnFailure ` , which only
299
+ distributed-process-extras provides an alternate function ` linkOnFailure ` , which only
300
300
dispatches the ` ProcessLinkException ` if the link-ed process dies abnormally (i.e., with
301
301
some ` DiedReason ` other than ` DiedNormal ` ).
302
302
@@ -305,7 +305,7 @@ putting a `ProcessMonitorNotification` into the process' mailbox. This signal an
305
305
constituent fields can be introspected in order to decide what action (if any) the receiver
306
306
can/should take in response to the monitored process' death. Let's take a look at how
307
307
monitors can be used to determine both when and _ how_ a process has terminated. Tucked
308
- away in distributed-process-platform , the ` linkOnFailure ` primitive works in exactly this
308
+ away in distributed-process-extras , the ` linkOnFailure ` primitive works in exactly this
309
309
way, only terminating the caller if the subject terminates abnormally. Let's take a look...
310
310
311
311
{% highlight haskell %}
@@ -366,17 +366,17 @@ process. The `ProcessInfo` type it returns contains the local node id and a list
366
366
registered names, monitors and links for the process. The call returns ` Nothing ` if the
367
367
process in question is not alive.
368
368
369
- ### Monad Transformer Stacks
369
+ ### Monad Transformer Stacks
370
370
371
- It is not generally necessary, but it may be convenient in your application to use a
372
- custom monad transformer stack with the Process monad at the bottom. For example,
371
+ It is not generally necessary, but it may be convenient in your application to use a
372
+ custom monad transformer stack with the Process monad at the bottom. For example,
373
373
you may have decided that in various places in your application you will make calls to
374
374
a network database. You may create a data access module, and it will need configuration information available to it in
375
- order to connect to the database server. A ReaderT can be a nice way to make
375
+ order to connect to the database server. A ReaderT can be a nice way to make
376
376
configuration data available throughout an application without
377
- schlepping it around by hand.
377
+ schlepping it around by hand.
378
378
379
- This example is a bit contrived and over-simplified but
379
+ This example is a bit contrived and over-simplified but
380
380
illustrates the concept. Consider the ` fetchUser ` function below, it runs in the ` AppProcess `
381
381
monad which provides the configuration settings required to connect to the database:
382
382
@@ -409,7 +409,7 @@ openDB = do
409
409
410
410
closeDB :: DB.Connection -> AppProcess ()
411
411
closeDB db = liftIO (DB.close db)
412
-
412
+
413
413
{% endhighlight %}
414
414
415
415
So this would mostly work but it is not complete. What happens if an exception
@@ -423,17 +423,17 @@ In the base library, [bracket][brkt] is defined in Control.Exception with this s
423
423
bracket :: IO a --^ computation to run first ("acquire resource")
424
424
-> (a -> IO b) --^ computation to run last ("release resource")
425
425
-> (a -> IO c) --^ computation to run in-between
426
- -> IO c
426
+ -> IO c
427
427
428
428
{% endhighlight %}
429
429
430
430
Great! We pass an IO action that acquires a resource; ` bracket ` passes that
431
431
resource to a function which takes the resource and runs another action.
432
- We also provide a release function which ` bracket ` is guaranteed to run
433
- even if the primary action raises an exception.
432
+ We also provide a release function which ` bracket ` is guaranteed to run
433
+ even if the primary action raises an exception.
434
434
435
435
436
- Unfortunately, we cannot directly use ` bracket ` in our
436
+ Unfortunately, we cannot directly use ` bracket ` in our
437
437
` fetchUser ` function: openDB (resource acquisition) runs in the ` AppProcess `
438
438
monad. If our functions ran in IO, we could lift the entire bracket computation into
439
439
our monad transformer stack with liftIO; but we cannot do that for the computations
@@ -473,7 +473,7 @@ onException p what = p `catch` \e -> do _ <- what
473
473
474
474
` distributed-process ` needs to do this sort of thing to keep its dependency
475
475
list small, but do we really want to write this for every transformer stack
476
- we use in our own applications? No! And we do not have to, thanks to
476
+ we use in our own applications? No! And we do not have to, thanks to
477
477
the [ monad-control] [ mctrl ] and [ lifted-base] [ lbase ] libraries.
478
478
479
479
[ monad-control] [ mctrl ] provides several typeclasses and helper functions
@@ -489,17 +489,17 @@ bracket that looks like this:
489
489
490
490
{% highlight haskell %}
491
491
492
- bracket :: MonadBaseControl IO m
492
+ bracket :: MonadBaseControl IO m
493
493
=> m a --^ computation to run first ("acquire resource")
494
494
-> (a -> m b) --^ computation to run last ("release resource")
495
495
-> (a -> m c) --^ computation to run in-between
496
- -> m c
496
+ -> m c
497
497
498
498
{% endhighlight %}
499
499
500
500
It is just the same as the version found in base, except it is generalized to work
501
501
with actions in any monad that implements [ MonadBaseControl IO] [ mbc ] . [ monad-control] [ mctrl ] defines
502
- instances for the standard transformers, but that instance requires the base monad
502
+ instances for the standard transformers, but that instance requires the base monad
503
503
(in this case, ` Process ` ) to also have an instance of these classes.
504
504
505
505
To address this the [ distributed-process-monad-control] [ dpmc ] package
@@ -520,7 +520,7 @@ fetchUser email =
520
520
Lifted.bracket openDB
521
521
closeDB
522
522
$ \db -> liftIO $ DB.query db email
523
-
523
+
524
524
525
525
{% endhighlight %}
526
526
0 commit comments