.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" 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 >0, 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 .. .if !\nF .nr F 0 .if \nF>0 \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} .\} .\" ======================================================================== .\" .IX Title "Message::Passing::Manual::Components 3pm" .TH Message::Passing::Manual::Components 3pm "2017-08-02" "perl v5.26.0" "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::Components \- Writing inputs, outputs and filters .SH "Writing your own scripts" .IX Header "Writing your own scripts" The supplied message-pass script is useful for testing, and is also fine for production use in simple cases, however, for less simple cases (for example scripts with multiple inputs or outputs), then the default script isn't suitable. .SS "Like the message-pass script" .IX Subsection "Like the message-pass script" If you just want to override some of the behavior of the message-pass script, to provide different details etc, then this is easy to do by subclassing the script. .PP An example of doing this is: .PP .Vb 4 \& package Message::Passing::Script::WebHooks; \& use Moo; \& use MooX::Options; \& use namespace::clean \-except => \*(Aqmeta\*(Aq; \& \& extends \*(AqMessage::Passing\*(Aq; \& \& option \*(Aq+encoder\*(Aq => ( \& init_arg => undef, \& default => \*(Aq+Message::Passing::Filter::Encoder::Null\*(Aq, \& nogetopt => 1, \& ); \& \& option \*(Aq+output\*(Aq => ( \& nogetopt => 1, \& ); \& \& _\|_PACKAGE_\|_\->start( output => \*(AqWebHooks\*(Aq ) unless caller; .Ve .PP This shows overriding the default command line options, as this script is dedicated to Message::Passing::Output::WebHooks. .SS "Different scripts" .IX Subsection "Different scripts" If you want a more complex example, rather than just overriding some of the functionality from the default script, then you're better off writing your own script. .PP See Message::Passing:Role::Script, for a basic role you are likely to want to use to do this. You'll also want to use Message::Passing::DSL, as shown in the example documentation for the script role.. .PP If you are writing your own script, want some components to be completely configurable (as per the default script), then see Message::Passing::Role::CLIComponent, which implements attributes to help you do this in the same way as the normal script (i.e. \&\f(CW\*(C`thing\*(C'\fR, and \f(CW\*(C`thing_options\*(C'\fR). .SH "Writing Filters" .IX Header "Writing Filters" A filter is just a class which consumes both Message::Passing::Role::Input and Message::Passing::Role::Output. .PP Simple filters can just consume Message::Passing::Role::Filter, and implement a \f(CW\*(C`filter\*(C'\fR method. Please see the documentation for that Role for more information. .PP More complex filters can compose the input and output roles themselves, and consume / emit messages as they choose. For a simple example of this type of filter, see Message::Passing::Filter::Delay. .SS "Encoders and Decoders" .IX Subsection "Encoders and Decoders" Encoders and Decoders are just implemented the same as standard filters. .PP The only difference is the default namespace supplied by the \s-1DSL,\s0 which appends \f(CW\*(C`Encoder::\*(C'\fR or \f(CW\*(C`Decoder::\*(C'\fR to the standard filter prefix. .SH "Writing Inputs and Outputs" .IX Header "Writing Inputs and Outputs" The interface for both inputs and outputs is conceptually very simple, however there are some gotchas to watch out for which are described below. .SS "Use common attributes." .IX Subsection "Use common attributes." Please try to keep the names of your component's attributes in keeping with the other inputs and outputs in the framework. .PP To help with this, a number of simple roles with attributes you may want are included in the distribution: .IP "Message::Passing::Role::HasHostnameAndPort" 4 .IX Item "Message::Passing::Role::HasHostnameAndPort" .PD 0 .IP "Message::Passing::Role::HasUsernameAndPassword" 4 .IX Item "Message::Passing::Role::HasUsernameAndPassword" .PD .SS "\s-1MUST\s0 by asynchronous." .IX Subsection "MUST by asynchronous." Your input or output \fB\s-1MUST NOT\s0\fR block in the course of it's normal operation. You should use AnyEvent to make your input or output asynchronous. .PP If you are trying to convert a synchronous module into being an input, then you can often make it \&'asynchronous enough' by grabbing the file descriptor and setting up an \s-1IO\s0 watcher on it. Message::Passing::Input::Freeswitch is an example of an input implemented like this. .SS "Connecting to a server." .IX Subsection "Connecting to a server." If your input or output connects to a server, you should be using the connection manager role supplied to manage this connection, rather than trying to manage it in your component directly. .PP This is so that users can have multiple inputs and outputs which share the same connection, which is both possible and desirable with a number of protocols. .PP Roles are provided to help component authors with this, please see the documentation in: .IP "Message::Passing::Role::HasAConnection \- for your component" 4 .IX Item "Message::Passing::Role::HasAConnection - for your component" .PD 0 .IP "Message::Passing::Role::ConnectionManager \- to implement your connection manager." 4 .IX Item "Message::Passing::Role::ConnectionManager - to implement your connection manager." .PD .PP For example code using these roles, see Message::Passing::STOMP, which implements a simple example. .SH "AUTHOR, COPYRIGHT & LICENSE" .IX Header "AUTHOR, COPYRIGHT & LICENSE" See Message::Passing.