The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

MooX::Failover - Instantiate Moo classes with failover

SYNOPSIS

  # In your class:

  package MyClass;

  use Moo;
  use MooX::Failover;

  has 'attr' => ( ... );

  # after attributes are defined:

  failover_to 'OtherClass';

  ...

  # When using the class

  my $obj = MyClass->new( %args );

  # If %args contains missing or invalid values or new otherwise
  # fails, then $obj will be of type "OtherClass".

DESCRIPTION

This module provides constructor failover for Moo classes.

For example, if a class cannot be instantiated because of invalid arguments (perhaps from an untrusted source), then instead it returns the failover class (passing the same arguments to that class).

It is roughly equivalent to using

  my $obj = eval { MyClass->new(%args) //
     OtherClass->new( %args, error => $@ );

This allows for cleaner design, by not forcing you to duplicate type checking for constructor parameters.

Use Cases

A use case for this module is for instantiating Web::Machine::Resource objects, where a resource class's attributes correspond to URL arguments. A type failure would normally cause an internal serror error (HTTP 500). Using MooX::Failover, we can return a different resource object that examines the error, and returns a more appropriate error code, e.g. bad request (HTTP 400).

Another use case for this module is for instantiating objects based on their data sources. For example, to restrieve an object from a cache, or to fail and retrieve it from the database instead.

Design Considerations

Your failover class should support the same methods as the original class, so that it (roughly) satisfies the Liskov Substitution Principle, where all provable properties of the original class are also provable of the failover class. In practice, we only care about the properties (methods and attributes) that are actually used in our programs.

EXPORTS

The following function is always exported:

failover_to

  failover_to $class => %options;

This specifies the class to instantiate if the constructor dies.

It should be specified after all of the attributes have been declared.

Chained failovers are allowed:

  failover_to $first  => %options1;
  failover_to $second => %options2;
  ...

The following options are supported.

class

The name of the class to fail over to. It defaults to $class.

constructor

The name of the constructor method in the failover class. It defaults to "new".

from_constructor

The name of the constructor in the class that you are adding failover to. It defaults to "new".

Note that you can add failovers to multiple constructors. Suppose your class has a "new" constructor, as well as a "new_from_file" constructor that loads information from a file and then calls "new". You can specify failovers for both of the constructors:

  failover_to 'OtherClass';

  failover_to 'OtherClass' => (
    from_constructor => 'new_from_file',
  );

This option was added in v0.3.0.

args

The arguments to pass to the failover class. When omitted, it will pass the same arguments as the original class.

This can be a scalar (single argument), hash reference or array reference.

Note that the options are treated are treated as raw Perl code. To use specify options, you need to explicitly add quotes to symbols, for example:

  failover_to 'OtherClass' => (
    args => [ map { "'$_'" } ( foo => 'bar' ) ],
  );

This option did not work properly until v0.3.0.

err_arg

This is the name of the constructor argument to pass the error to (it defaults to "error". This is useful if the failover class can inspect the error and act appropriately.

For example, if the original class is a handler for a website, where the attributes correspond to URL parameters, then the failover class can return HTTP 400 responses if the errors are for invalid parameters.

To disable it, set it to undef.

class_arg

This is the name of the constructor argument to pass the name of the original class that failed. It defaults to "class".

To disable it, set it to undef.

For chained failovers, it always contains the name of the original class.

orig_arg

This is the name of the constructor to pass an array reference of the original arguments passed to class. It is undef by default.

The original arguments are already passed to the failover class, but this can be used to pass them all in a specific parameter.

If you do not want the original arguments passed to the failover class separately, set the args option to be empty:

  failover_to 'OtherClass' => (
    args      => [ ],
    orig_args => 'failed_args',
  );

This option was added in v0.3.0.

Note that unimporting Moo using

  no Moo;

will also unimport MooX::Failover.

ATTRIBUTES

None. Since v0.2.0, there is no longer a failover_to attribute.

SEE ALSO

This was originally a Moo port of MooseX::Failover. The interface was redesigned significantly, to be more efficient.

AUTHOR

Robert Rothenberg <rrwo@thermeon.com>

Acknowledgements

Thermeon.
Piers Cawley.
Gareth Kirwan

COPYRIGHT

Copyright 2014 Thermeon Worldwide, PLC.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.