Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Workflow CPAN distribution.

Report information
The Basics
Id: 45711
Status: resolved
Priority: 0/
Queue: Workflow

People
Owner: jonasbn [...] cpan.org
Requestors: peebles [...] cortina-systems.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.32
Fixed in: (no value)



Subject: Workflow::State Persistence
Date: Mon, 04 May 2009 15:42:09 -0700
To: bug-Workflow [...] rt.cpan.org
From: Andrew Peebles <peebles [...] cortina-systems.com>
I am using Workflow-1.32 in a web application using FastCGI (Catalyst), which means the application server (the perl program using Workflow) is persistent across calls from user clients ... this is for performance ... the application should still behave as if it were running under CGI from a programmer's point of view. 

Anyway, I am seeing what I think is an issue with using Workflow under these circumstances.  The package BTW is truly awesome; the best in this category that I have seen.

The problem is that
  1. Workflow::State remembers past condition checks via $self->{'_condition_result_cache'}
  2. Factory creates once, and remembers the list of Workflow::State objects for a Workflow, and attaches this persistent list (_workflow_states) to workflows when created or fetched.
Because of these two facts, cached conditions can bleed from one workflow instance to another.  In my senerio I have a workflow that has actions that are dependent on the conditions "IsOwner" and "IsManager".  What seems to happen is that when a "manager" references a particular workflow during one client connection to the app, and then an "owner" references the same workflow (via id ... a "fetch" is performed at beginning of each connection), the condition results from the first connection carry over into the state for the second condition, and I see:

    'No access to action 'Finished Editing' in state 'INITIAL' because cached condition 'IsOwner' already failed before.'

It took me a while to track this down.  My "fix" is to install an Observer on "create" and "fetch" that:

sub update {
    my ( $class, $wf, $event, $new_state ) = @_;
    return unless( $event eq 'fetch' ||
                   $event eq 'create' );
    foreach my $state ( keys( %{$wf->{_states}} ) ) {
        $wf->{_states}->{$state}->clear_condition_cache();
    }
}

Unfortunately I must peek into internal data structures to do this.  I am pretty sure this solution is valid for my application ... which should essentially act like a CGI, in that from a programmers model point of view, should be completely torn down and restarted on each client connection.  That would mean that there would be no chance for Workflow::State internal, dynamic variables to bleed across workflow "fetches".

I am thinking that the workflow list of states, when a workflow is created or fetched, should be "clean", possibly a copy of the original list created by the Factory instead of a reference to a single list.



Issue migrated to Github: https://github.com/jonasbn/perl-workflow/issues/7 jonasbn