The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

POE::Component::StackedProcessor - Stacked Processors In POE

SYNOPSIS

  use POE::Component::StackedProcessor;
  my $p = POE::Component::StackedProcessor->new(
    Alias      => $alias,
    InlineStates => {  # or PackageStates/ObjectStates
      success => \&success_cb,
      failure => \&failure_cb
    }
  );
  $p->add(state1 => $proc1);
  $p->add(state2 => $proc2, $decision);
  $p->add(state3 => $proc3);
  POE::Kernel->run();

  # else where in the code...
  $kernel->post($alias, 'process', 'success', 'failure', $input);

DESCRIPTION

POE::Component::StackedProcessor allows you to build a chain of processors whose dispatching depends on the successful completion of the previous processor.

For example, suppose you have an HTML document that requires you to verify whethere it meats certain criteria such as proper markup, valid links, etc. Normally this would be done in one pass for the sake of efficiency, but sometimes you want to break these steps up into several components such that you can mix and match the different processors as required.

In a very simple stacked processor where the processors are run in linear fashion, all you need to do is to create the processor, and then add the states in the order that you want them to be executed:

  use POE::Component::StackedProcessor;
  sub success_state {
    my($response) = @_[ARG1];
    ...
  }

  sub failure_state {
    my($response) = @_[ARG1];
    ...
  }

  my $p = POE::Component::StackedProcessor->new(
    Alias        => $alias,
    InlineStates => {
      success => \&success_state,
      failure => \&failure_state,
    }
  );

  my $p1 = MyProcessor1->new();
  my $p2 = MyProcessor2->new();
  my $p3 = MyProcessor3->new();

  $p->add($name1, $p1);
  $p->add($name2, $p2);
  $p->add($name3, $p3);

  POE::Kernel->post($alias, 'process', 'success', 'failure', $input);
  POE::Kernel->run();

In the above example, $p1, $p2, $p3 are executed in order. If all processors are run to completion, then the 'success' state (or whatever you specified in the third argument to post()) is called. Otherwise, the 'failure' state (the fourth argument to post()) is called.

However, sometimes you want to control the execution order. In such cases, you can use add()'s third parameter, which is the "decision maker" parameter. This argument can be a coderef or an object, and is responsible for returning the key for next processor to be run.

  $p->add($name1, $p1, $dm);

For example, if you had stated P1, P2, P3, and you want to only run P2 if P1 succeeded, then you can do this:

  sub skip_if_p1_failed {
    my($p, $prdata, $result) = @_;

    # where $p      is the POE::Component::StackedProcessor
    #       $prdata is the current processor's information (as hashref)
    #       $result is the return value from the the current processor

    if (!defined $result) {
      return 'P3';
    } else {
      return 'P2';
    }
  }

  $p->add(P1 => $p1, \&skip_if_p1_failed);
  $p->add(P2 => $p2);
  $p->add(P3 => $p3);

Note, though, that you can use numerical indices to indicate the next processor to be run. So instead of the last 5 lines of skip_if_p1_failed, you can say:

  if (!defined $result) {
     return 2;
  } else {
     return 1;
  }

The success/failure callbacks receive the arguments that a POE postback state receives. Namely ARG0 maps to the "request" argument list and, and ARG1 maps to the "response" argument list.

METHODS

new ARGS

Alias

Alias of the StackedProcessor session. (You probably want to set this, because you will need to post() to this session to run the processors)

InlineStates/Packagestates/ObjectStates

Optional states to faciliate your method dispatching. You can, for example, set success and failure states there that gets called upon successful execution.

callback_name

This is a class-method to specify at run time what method name should be called on the processor objects. The default is "process".

alias

Gets the alias given to the session for this stack processor

CAVEATS

The processor name must *not* look like a number. If it looks like a number, then it will be taken as an index in the processor list, not a processor name.

SEE ALSO

POE

AUTHOR

Daisuke Maki <dmaki@cpan.org>