… | |
… | |
477 | still be there, by recovering and restarting the service. |
477 | still be there, by recovering and restarting the service. |
478 | |
478 | |
479 | AnyEvent::MP supports this by catching exceptions and network problems, |
479 | AnyEvent::MP supports this by catching exceptions and network problems, |
480 | and notifying interested parties of this. |
480 | and notifying interested parties of this. |
481 | |
481 | |
482 | =head2 Exceptions, Network Errors and Monitors |
482 | =head2 Exceptions, Port Context, Network Errors and Monitors |
483 | |
483 | |
484 | =head3 Exceptions |
484 | =head3 Exceptions |
485 | |
485 | |
486 | Exceptions are handled on a per-port basis: receive callbacks are executed |
486 | Exceptions are handled on a per-port basis: receive callbacks are executed |
487 | in a special context, the port-context, and code that throws an uncaught |
487 | in a special context, the so-called I<port-context>: code that throws an |
488 | exception will cause the port to be C<kil>led. Killed ports are destroyed |
488 | otherwise uncaught exception will cause the port to be C<kil>led. Killed |
489 | automatically (killing ports is the only way to free ports, incidentally). |
489 | ports are destroyed automatically (killing ports is the only way to free |
|
|
490 | ports, incidentally). |
490 | |
491 | |
491 | Ports can be monitored, even from a different host, and when a port is |
492 | Ports can be monitored, even from a different host, and when a port is |
492 | killed any entity monitoring it will be notified. |
493 | killed any entity monitoring it will be notified. |
493 | |
494 | |
494 | Here is a simple example: |
495 | Here is a simple example: |
… | |
… | |
575 | }; |
576 | }; |
576 | |
577 | |
577 | Then you will find it does not work - when the after callback is executed, |
578 | Then you will find it does not work - when the after callback is executed, |
578 | it does not run in port context anymore, so exceptions will not be caught. |
579 | it does not run in port context anymore, so exceptions will not be caught. |
579 | |
580 | |
580 | For these cases, AnyEvent::MP exports a special "close constructor" called |
581 | For these cases, AnyEvent::MP exports a special "closure constructor" |
581 | C<psub>, which works just like perl's builtin C<sub>: |
582 | called C<psub>, which works just like perl's builtin C<sub>: |
582 | |
583 | |
583 | my $port = port { |
584 | my $port = port { |
584 | after 1, psub { die "oops" }; |
585 | after 1, psub { die "oops" }; |
585 | }; |
586 | }; |
586 | |
587 | |
587 | C<psub> stores C<$SELF> and returns a code reference. When the code |
588 | C<psub> stores C<$SELF> and returns a code reference. When the code |
588 | reference is invoked, it will run the code block within the context of |
589 | reference is invoked, it will run the code block within the context of |
589 | that port, so exception handling once more works as expected. |
590 | that port, so exception handling once more works as expected. |
|
|
591 | |
|
|
592 | There is also a way to temporarily execute code in the context of some |
|
|
593 | port, namely C<peval>: |
|
|
594 | |
|
|
595 | peval $port, sub { |
|
|
596 | # die'ing here will kil $port |
|
|
597 | }; |
|
|
598 | |
|
|
599 | The C<peval> function temporarily replaces C<$SELF> by the given C<$port> |
|
|
600 | and then executes the given sub in a port context. |
590 | |
601 | |
591 | =head3 Network Errors and the AEMP Guarantee |
602 | =head3 Network Errors and the AEMP Guarantee |
592 | |
603 | |
593 | I mentioned another important source of monitoring failures: network |
604 | I mentioned another important source of monitoring failures: network |
594 | problems. When a node loses connection to another node, it will invoke all |
605 | problems. When a node loses connection to another node, it will invoke all |