File Coverage

blib/lib/Workflow/Persister.pm
Criterion Covered Total %
statement 59 60 98.3
branch 12 12 100.0
condition 5 7 71.4
subroutine 17 18 94.4
pod 11 11 100.0
total 104 108 96.3


line stmt bran cond sub pod time code
1             package Workflow::Persister;
2              
3 34     34   1333725 use warnings;
  34         107  
  34         2522  
4 34     34   228 use strict;
  34         88  
  34         1003  
5 34     34   644 use 5.013002;
  34         121  
6 34     34   182 use parent qw( Workflow::Base );
  34         69  
  34         280  
7 34     34   6894 use Workflow::Exception qw( persist_error );
  34         76  
  34         2147  
8 34     34   4587 use Syntax::Keyword::Try;
  34         19246  
  34         281  
9              
10 34     34   3865 use constant DEFAULT_ID_LENGTH => 8;
  34         63  
  34         50215  
11              
12             $Workflow::Persister::VERSION = '2.09';
13              
14             my @FIELDS = qw( name class
15             use_random use_uuid
16             workflow_id_generator history_id_generator );
17             __PACKAGE__->mk_accessors(@FIELDS);
18              
19             sub init {
20 22     22 1 76 my ( $self, $params ) = @_;
21 22         102 for (@FIELDS) {
22 132 100       1485 $self->$_( $params->{$_} ) if ( $params->{$_} );
23             }
24 22 100       175 unless ( $self->use_random ) {
25 21         443 $self->use_random('no');
26             }
27 22 100       379 unless ( $self->use_uuid ) {
28 21         296 $self->use_uuid('no');
29             }
30 22         338 $self->log->info( "Initializing persister '", $self->name, "'" );
31             }
32              
33             ########################################
34             # COMMON GENERATOR ASSIGNMENTS
35              
36             sub assign_generators {
37 24     24 1 12149 my ( $self, $params ) = @_;
38 24   100     114 $params ||= {};
39              
40 24         63 my ( $wf_gen, $history_gen );
41 24 100       116 if ( $self->use_uuid eq 'yes' ) {
    100          
42 2         35 $self->log->debug("Assigning UUID generators by request");
43 2         11 ( $wf_gen, $history_gen ) = $self->init_uuid_generators($params);
44             } elsif ( $self->use_random eq 'yes' ) {
45 5         148 $self->log->debug("Assigning random ID generators by request");
46 5         41 ( $wf_gen, $history_gen ) = $self->init_random_generators($params);
47             }
48 22 100 66     626 if ( $wf_gen and $history_gen ) {
49 5         36 $self->workflow_id_generator($wf_gen);
50 5         91 $self->history_id_generator($history_gen);
51             }
52             }
53              
54             sub init_random_generators {
55 21     21 1 64 my ( $self, $params ) = @_;
56 21   50     166 my $length = $params->{id_length} || DEFAULT_ID_LENGTH;
57             try {
58             require Workflow::Persister::RandomId;
59             }
60 21         69 catch ($msg) {
61             my $logmsg = ($msg =~ s/\\n/ /gr);
62             $self->log->error($logmsg);
63             die $msg;
64             }
65 20         289 my $generator
66             = Workflow::Persister::RandomId->new( { id_length => $length } );
67 20         95 return ( $generator, $generator );
68             }
69              
70             sub init_uuid_generators {
71 2     2 1 5 my ( $self, $params ) = @_;
72              
73             try {
74             require Workflow::Persister::UUID
75             }
76 2         7 catch ($msg) {
77             my $logmsg = ($msg =~ s/\\n/ /gr);
78             $self->log->error($logmsg);
79             die $msg;
80             }
81 1         9 my $generator = Workflow::Persister::UUID->new();
82 1         5 return ( $generator, $generator );
83             }
84              
85             ########################################
86             # INTERFACE METHODS
87              
88             sub create_workflow {
89 1     1 1 742 my ( $self, $wf ) = @_;
90 1         4 persist_error "Persister '", ref($self), "' must implement ",
91             "'create_workflow()'";
92             }
93              
94             sub update_workflow {
95 1     1 1 1645 my ( $self, $wf ) = @_;
96 1         4 persist_error "Persister '", ref($self), "' must implement ",
97             "'update_workflow()'";
98             }
99              
100             sub fetch_workflow {
101 1     1 1 1354 my ( $self, $wf_id ) = @_;
102 1         5 persist_error "Persister '", ref($self), "' must implement ",
103             "'fetch_workflow()'";
104             }
105              
106             sub create_history {
107 1     1 1 1352 my ( $self, $wf, @history ) = @_;
108 1         6 persist_error "Persister '", ref($self), "' must implement ",
109             "'create_history()'";
110             }
111              
112             sub fetch_history {
113 1     1 1 1426 my ( $self, $wf ) = @_;
114 1         4 persist_error "Persister '", ref($self), "' must implement ",
115             "'fetch_history()'";
116             }
117              
118             # Only required for DBI persisters.
119             sub commit_transaction {
120 8     8 1 21 return;
121             }
122              
123             sub rollback_transaction {
124 0     0 1   return;
125             }
126              
127             1;
128              
129             __END__
130              
131             =pod
132              
133             =head1 NAME
134              
135             Workflow::Persister - Base class for workflow persistence
136              
137             =head1 VERSION
138              
139             This documentation describes version 2.09 of this package
140              
141             =head1 SYNOPSIS
142              
143             # Associate a workflow with a persister in workflow.yaml
144             type: Ticket
145             persister: MainDatabase
146             state:
147             ...
148              
149             # Declare a persister in persister.yaml
150             persister:
151             - name: MainDatabase
152             class: Workflow::Persister::DBI
153             driver: MySQL
154             dsn: DBI:mysql:database=workflows
155             user: wf
156             password: mypass
157              
158             # Declare a separate persister in other_persister.yaml
159             persister:
160             - name: FileSystem
161             class: Workflow::Persister::File
162             path: /path/to/my/workflow
163              
164             =head1 DESCRIPTION
165              
166             This is the base class for persisting workflows. It does not implement
167             anything itself but actual implementations should subclass it to
168             ensure they fulfill the contract.
169              
170             The job of a persister is to create, update and fetch the workflow
171             object plus any data associated with the workflow. It also creates and
172             fetches workflow history records.
173              
174             =head1 SUBCLASSING
175              
176             =head2 Methods
177              
178             =head3 create_workflow( $workflow )
179              
180             Stub that warns that the method should be overwritten in the derived
181             Persister. Since this is a SUPER class.
182              
183             Generate an ID for the workflow, serialize the workflow data (ID and
184             state) and set the ID in the workflow.
185              
186             Returns the ID for the workflow.
187              
188             =head3 update_workflow( $workflow )
189              
190             Stub that warns that the method should be overwritten in the derived
191             Persister. Since this is a SUPER class.
192              
193             Update the workflow state including serialization of the workflow
194             context.
195              
196             Returns nothing.
197              
198             =head3 fetch_workflow( $workflow_id )
199              
200             Stub that warns that the method should be overwritten in the derived
201             Persister. Since this is a SUPER class.
202              
203             Retrieve the workflow data corresponding to C<$workflow_id>. It not
204             found return undef, if found return a hashref with at least the keys
205             C<state> and C<last_update> (a L<DateTime> instance).
206              
207             If the workflow has associated serialized context, return the
208             deserialized hash value in the C<context> key. The keys in the hash
209             will be made available through the C<param> method in the workflow's
210             context (accessible through the C<context> method).
211              
212             =head3 create_history( $workflow, @history )
213              
214             Stub that warns that the method should be overwritten in the derived
215             Persister. Since this is a SUPER class.
216              
217             Serialize all objects in C<@history> for later retrieval.
218              
219             Returns C<@history>, the list of history objects, with the history
220             C<id> and C<saved> values set according to the saved results.
221              
222             =head3 fetch_history( $workflow )
223              
224             Stub that warns that the method should be overwritten in the derived
225             Persister. Since this is a SUPER class.
226              
227             The derived class method should return a list of hashes containing at least
228             the `id` key. The hashes will be used by the workflow object to instantiate
229             L<Workflow::History> objects (or a derived class).
230              
231              
232             =head3 assign_generators( \%params )
233              
234             Assigns proper generators based on intialization, see L</init>
235              
236             =head3 commit_transaction
237              
238             Commit the current transaction if the persister supports transactions.
239             This stub does not have to be overridden. It is not executed if
240             autocommit is on.
241              
242             =head3 rollback_transaction
243              
244             Roll back the current transaction if the persister supports transactions.
245             This stub does not have to be overridden. It is not executed if
246             autocommit is on.
247              
248             =head3 init
249              
250             Method to initialize persister based on configuration.
251              
252             =head3 init_random_generators( \%params )
253              
254             Initializes random id generators, takes the following named parameters:
255              
256             =over
257              
258             =item * length, of random id to be generated
259              
260             =back
261              
262             Returns two identical random id generator objects in list context.
263              
264             =head3 init_uuid_generators( \%params )
265              
266             Initializes UUID generators, takes no parameters
267              
268             Returns two identical UUID generator objects in list context.
269              
270             =head1 TODO
271              
272             =over
273              
274             =item * refactor init_random_generators, returns two similar objects?
275              
276             =item * refactor init_uuid_generators, returns two similar objects?
277              
278             =item * refactor init_uuid_generators, takes no parameters, even though
279             we shift parameters in?
280              
281             =back
282              
283             =head1 SEE ALSO
284              
285             =over
286              
287             =item * L<Workflow::Factory>
288              
289             =item * L<Workflow::History>
290              
291             =back
292              
293             =head1 COPYRIGHT
294              
295             Copyright (c) 2003-2021 Chris Winters. All rights reserved.
296              
297             This library is free software; you can redistribute it and/or modify
298             it under the same terms as Perl itself.
299              
300             Please see the F<LICENSE>
301              
302             =head1 AUTHORS
303              
304             Please see L<Workflow>
305              
306             =cut