NAME
Stepford::Runner - Takes a set of steps and figures out what order to run them in
VERSION
version 0.006001
SYNOPSIS
use Stepford::Runner;
my $runner = Stepford::Runner->new(
step_namespaces => 'My::Step',
);
$runner->run(
final_steps => [
'My::Step::DeployCatDatabase',
'My::Step::DeployDogDatabase',
],
config => {...},
);
DESCRIPTION
This class takes a set of objects which do the Stepford::Role::Step role and determines what order they should be run so as to get to one or more final steps.
Steps which are up to date are skipped during the run, so no unnecessary work is done.
METHODS
This class provides the following methods:
Stepford::Runner->new(...)
This method returns a new runner object. It accepts the following arguments:
step_namespaces
This argument is required.
This can either be a string or an array reference of strings. Each string should contain a namespace which contains step classes.
For example, if your steps are named
My::Step::CreateFoo
,My::Step::MergeFooAndBar
, andMy::Step::DeployMergedFooAndBar
, the namespace you'd provide is'My::Step'
.The order of the step namespaces is relevant. If more than one step has a production of the same name, then the first step "wins". Stepford sorts step class names based on the order of the namespaces provided to the constructor, and then the full name of the class. You can take advantage of this feature to provide different steps in different environments (for example, for testing).
The runner object assumes that every class it finds in a step namespace is a step. Specifically, if it finds a package that is a subclass of Moose::Object, then it throws an error if that package does not also consume the Stepford::Role::Step role.
This means you can have utility packages and roles in a step namespace, but not Moose objects which aren't steps.
jobs
This argument defaults to 1.
The number of jobs to run at a time. By default, all steps are run sequentially. However, if you set this to a value greater than 1 then the runner will run steps in parallel, up to the value you set.
logger
This argument is optional.
This should be an object that provides
debug
,info
,notice
,warning
, anderror
methods.This object will receive log messages from the runner and (possibly your steps).
If this is not provided, Stepford will create a Log::Dispatch object with a single Log::Dispatch::Null output (which silently eats all the logging messages).
Note that if you do provide a logger object of your own, Stepford will not load Log::Dispatch into memory.
$runner->run
When this method is called, the runner comes up with a plan of the steps needed to get to the requested final steps.
When this method is called, we check for circular dependencies among the steps and will throw a Stepford::Error exception if it finds one. We also check for unsatisfied dependencies for steps in the plan. Finally, we check to make sure that no step provides its own dependencies as productions.
For each step, the runner checks if it is up to date compared to its dependencies (as determined by the $step->last_run_time
method. If the step is up to date, it is skipped, otherwise the runner calls $step->run
on the step. You can avoid this check and force all steps to be executed with the force_step_execution
parameter (documented below.)
Note that the step objects are always constructed, so you should avoid doing a lot of work in your constructor. Save that for the run
method.
This method accepts the following parameters:
final_steps
This argument is required.
This can either be a string or an array reference of strings. Each string should be a step's class name. These classes must do the Stepford::Role::Step role.
These are the final steps run when the
$runner->run
method is called.config
This is an optional hash reference. For each step constructed, the runner looks at the attributes that the step accepts. If they match any of the keys in this hash reference, the key/value pair from this hash reference will be passed to the step constructor. This matching is done based on attribute
init_arg
values.Note that values generated as productions from previous steps will override the corresponding key in the config hash reference.
force_step_execution
This argument defaults to false.
This controls if we should force all steps to be executed rather than checking which steps are up to date and do not need re-executing. Even with this set each step will only be executed once per run regardless of how many other steps depend on it during execution.
dry_run
The argument is a boolean that defaults to false. When set to a true value, Stepford prints out the steps that need to be executed and exits without executing them.
$runner->step_namespaces
This method returns the step namespaces passed to the constructor as a list (not an arrayref).
$runner->logger
This method returns the logger
used by the runner, either what you passed to the constructor or a default.
PARALLEL RUNS AND SERIALIZATION
When running steps in parallel, the results of a step (its productions) are sent from a child process to the parent by serializing them. This means that productions which can't be serialized (like a filehandle or DBI handle) will cause the runner to die when it tries to serialize their productions.
You can force a step class to be run in the same process as the runner itself by having that step consume the Stepford::Role::Step::Unserializable role. Note that the runner may still fork after a production has been generated, so the values returned for a production must be able to survive a fork, even if they cannot be serialized.
You can also work around this by changing the production entirely. For example, instead of passing a DBI handle you could pass a data structure with a DSN, username, password, and connection options.
SUPPORT
Bugs may be submitted through https://github.com/maxmind/Stepford/issues.
AUTHOR
Dave Rolsky <drolsky@maxmind.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2014 - 2023 by MaxMind, Inc.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.