AnyEvent-MP

 view release on metacpan or  search on metacpan

MP.pm  view on Meta::CPAN

=item * The AEMP protocol is optimised for both text-based and binary
communications.

The AEMP protocol, unlike the Erlang protocol, supports both programming
language independent text-only protocols (good for debugging), and binary,
language-specific serialisers (e.g. Storable). By default, unless TLS is
used, the protocol is actually completely text-based.

It has also been carefully designed to be implementable in other languages
with a minimum of work while gracefully degrading functionality to make the
protocol simple.

=item * AEMP has more flexible monitoring options than Erlang.

In Erlang, you can chose to receive I<all> exit signals as messages or
I<none>, there is no in-between, so monitoring single Erlang processes is
difficult to implement.

Monitoring in AEMP is more flexible than in Erlang, as one can choose
between automatic kill, exit message or callback on a per-port basis.

=item * Erlang tries to hide remote/local connections, AEMP does not.

Monitoring in Erlang is not an indicator of process death/crashes, in the
same way as linking is (except linking is unreliable in Erlang).

In AEMP, you don't "look up" registered port names or send to named ports
that might or might not be persistent. Instead, you normally spawn a port
on the remote node. The init function monitors you, and you monitor the
remote port. Since both monitors are local to the node, they are much more
reliable (no need for C<spawn_link>).

This also saves round-trips and avoids sending messages to the wrong port
(hard to do in Erlang).

=back

=head1 RATIONALE

=over 4

=item Why strings for port and node IDs, why not objects?

We considered "objects", but found that the actual number of methods
that can be called are quite low. Since port and node IDs travel over
the network frequently, the serialising/deserialising would add lots of
overhead, as well as having to keep a proxy object everywhere.

Strings can easily be printed, easily serialised etc. and need no special
procedures to be "valid".

And as a result, a port with just a default receiver consists of a single
code reference stored in a global hash - it can't become much cheaper.

=item Why favour JSON, why not a real serialising format such as Storable?

In fact, any AnyEvent::MP node will happily accept Storable as framing
format, but currently there is no way to make a node use Storable by
default (although all nodes will accept it).

The default framing protocol is JSON because a) JSON::XS is many times
faster for small messages and b) most importantly, after years of
experience we found that object serialisation is causing more problems
than it solves: Just like function calls, objects simply do not travel
easily over the network, mostly because they will always be a copy, so you
always have to re-think your design.

Keeping your messages simple, concentrating on data structures rather than
objects, will keep your messages clean, tidy and efficient.

=back

=head1 PORTING FROM AnyEvent::MP VERSION 1.X

AEMP version 2 has a few major incompatible changes compared to version 1:

=over 4

=item AnyEvent::MP::Global no longer has group management functions.

At least not officially - the grp_* functions are still exported and might
work, but they will be removed in some later release.

AnyEvent::MP now comes with a distributed database that is more
powerful. Its database families map closely to port groups, but the API
has changed (the functions are also now exported by AnyEvent::MP). Here is
a rough porting guide:

  grp_reg $group, $port                      # old
  db_reg $group, $port                       # new

  $list = grp_get $group                     # old
  db_keys $group, sub { my $list = shift }   # new

  grp_mon $group, $cb->(\@ports, $add, $del) # old
  db_mon $group, $cb->(\%ports, $add, $change, $del) # new

C<grp_reg> is a no-brainer (just replace by C<db_reg>), but C<grp_get> is
no longer instant, because the local node might not have a copy of the
group. You can either modify your code to allow for a callback, or use
C<db_mon> to keep an updated copy of the group:

  my $local_group_copy;
  db_mon $group => sub { $local_group_copy = $_[0] };

  # now "keys %$local_group_copy" always returns the most up-to-date
  # list of ports in the group.

C<grp_mon> can be replaced by C<db_mon> with minor changes - C<db_mon>
passes a hash as first argument, and an extra C<$chg> argument that can be
ignored:

  db_mon $group => sub {
     my ($ports, $add, $chg, $del) = @_;
     $ports = [keys %$ports];

     # now $ports, $add and $del are the same as
     # were originally passed by grp_mon.
     ...
  };



( run in 0.732 second using v1.01-cache-2.11-cpan-39bf76dae61 )