.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Message::Passing::Manual::Concepts 3pm" .TH Message::Passing::Manual::Concepts 3pm "2016-07-04" "perl v5.22.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Message::Passing::Manual::Concepts \- The concepts behind the framework .SH "DESCRIPTION" .IX Header "DESCRIPTION" This framework tries to be a simplifying layer over message passing, allowing you to easily make the networking parts of message passing become just configuration. This allows you to concentrate on the hard parts (i.e. your application, not the message passing). .SH "COMPONENTS AND CHAINS" .IX Header "COMPONENTS AND CHAINS" There are only a few core concepts to grasp to use the framework. We'll start with the component types, and then move onto chains. .PP There are only three types of components: .SS "\s-1OUTPUTS\s0" .IX Subsection "OUTPUTS" An output is simply a class with a \f(CW\*(C`consume\*(C'\fR method. This will be called with a message as it's only parameter, like this: .PP .Vb 1 \& $output\->consume($message); .Ve .PP Outputs are expected to compose Message::Passing::Role::Output. .SS "\s-1INPUTS\s0" .IX Subsection "INPUTS" An input is simply a class with an \f(CW\*(C`output_to\*(C'\fR attribute. Your code just calls the consume method on it's output, like this: .PP .Vb 1 \& $self\->output_to\->consume($message); .Ve .PP Inputs are expected to compose Message::Passing::Role::Input which provides this attribute, and use the \f(CW\*(C`BUILD\*(C'\fR method from Moo to do any work needed to start listening for events. .SS "\s-1FILTER\s0" .IX Subsection "FILTER" A filter is just a combination of an output and input. Some (or all) of the messages consumed by the input are sent on to the output. .PP An optional Message::Passing::Role::Filter is supplied, allowing you to provide a simple filter method: .PP .Vb 1 \& with \*(AqMessage::Passing::Role::Filter\*(Aq; \& \& sub filter { \& my ($self, $message) = @_; \& return $message; # Or return undef to drop it \& } .Ve .PP However, you can write a filter manually as: .PP .Vb 4 \& with qw/ \& Message::Passing::Role::Input \& Message::Passing::Role::Output \& /; \& \& sub consume { \& my ($self, $message) = @_; \& # Do something to $message here \& $self\->output_to\->consume($message); \& } .Ve .PP As you've hopefully guessed now, a \f(CW\*(C`chain\*(C'\fR is just an input, outputting to zero or more filters, which output to an output. .SH "DSL" .IX Header "DSL" So, this is all pretty easy, and you already know enough to pick up some components and use them! For example: .PP .Vb 2 \& use Message::Passing::Input::FileTail; \& use Message::Passing::Output::STDOUT; \& \& Message::Passing::Input::FileTail\->new( \& filename => $ARGV[0], \& output_to => Message::Passing::Output::STDOUT\->new, \& ); \& AnyEvent\->condvar\->recv; # Enter event loop .Ve .PP There you go \- you're tailing a file to screen \- however you could just as easily by sending it over the network with ZeroMQ or any other output. .PP This is, however, a bit ugly! If you're building a chain of several filters, or you have several inputs being multiplexed into one output, then the code gets ugly fast. .PP To make it easy to build chains of processing, and your own scripts, a simple \s-1DSL\s0 is provided. The example above becomes: .PP .Vb 1 \& use Message::Passing::DSL; \& \& run_message_server message_chain { \& input file => ( \& class => \*(AqFileTail\*(Aq, \& output_to => \*(Aqstdout\*(Aq, \& ); \& output stdout => ( \& class => \*(AqSTDOUT\*(Aq, \& ); \& }; .Ve .SH "Event loop" .IX Header "Event loop" AnyEvent has been mentioned, and it's expected that scripts will use a supported event loop. This implies that your code is asynchronous, which is generally fine \- however it should be noted that doing any long operation (non trivial database queries) will block the entire server \- meaning no events will be processed. .PP In cases such as these, running a pool of worker processes to distribute the blocking jobs is more appropriate, and easy to wire up (on one or more hosts). This is documented more fully in Message::Passing::Manual::Workers .SH "ZeroMQ" .IX Header "ZeroMQ" ZeroMQ is the recommended transport for messages, and Message::Passing::Output::ZeroMQ is designed to work inside a traditional synchronous application. This means that you can emit messages into ZeroMQ without blocking your application, or having to use or run the AnyEvent event loop. .SH "SEE ALSO" .IX Header "SEE ALSO" .SS "Message::Passing::Manual::Cookbook" .IX Subsection "Message::Passing::Manual::Cookbook" Recipies for achieving common tasks .SH "AUTHOR, COPYRIGHT & LICENSE" .IX Header "AUTHOR, COPYRIGHT & LICENSE" See Message::Passing.