# #-- # Copyright (c) 2007, Tomaso Tosolini, John Mettraux OpenWFE.org # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # . Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # . Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # . Neither the name of the "OpenWFE" nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #++ # # # "made in Italy" # # Tomaso Tosolini # John Mettraux # require 'rubygems' #require_gem 'activerecord' gem 'activerecord' require 'active_record' require 'monitor' require 'openwfe/service' require 'openwfe/rudefinitions' require 'openwfe/expool/expstorage' require 'openwfe/expool/threadedexpstorage' module OpenWFE::Extras # # A migration for creating/dropping the "expressions" table. # 'expressions' are atomic pieces of running process instances. # class ExpressionTables < ActiveRecord::Migration def self.up create_table :expressions do |t| t.column :fei, :string, :null => false t.column :wfid, :string, :null => false #t.column :wfname, :string, :null => false t.column :exp_class, :string, :null => false t.column :svalue, :text, :null => false # 'value' could be reserved, using 'svalue' instead end add_index :expressions, :fei add_index :expressions, :wfid #add_index :expressions, :wfname add_index :expressions, :exp_class end def self.down drop_table :expressions end end # # The ActiveRecord wrapper for an OpenWFEru FlowExpression instance. # class Expression < ActiveRecord::Base serialize :svalue end # # Storing OpenWFE flow expressions in a database. # class DbExpressionStorage include MonitorMixin include OpenWFE::ServiceMixin include OpenWFE::OwfeServiceLocator include OpenWFE::ExpressionStorageBase # # Constructor. # def initialize (service_name, application_context) require 'openwfe/storage/yamlcustom' # making sure this file has been required at this point # this yamlcustom thing prevents the whole OpenWFE ecosystem # to get serialized :) super() # absolutely necessary as we include MonitorMixin service_init service_name, application_context observe_expool end # # Stores an expression. # def []= (fei, flow_expression) ldebug { "[]= storing #{fei.to_s}" } synchronize do e = Expression.find_by_fei fei.to_s unless e e = Expression.new e.fei = fei.to_s e.wfid = fei.wfid #e.wfname = fei.wfname end e.exp_class = flow_expression.class.name e.svalue = flow_expression e.save! end end # # Retrieves a flow expression. # def [] (fei) e = Expression.find_by_fei fei.to_s return nil unless e as_owfe_expression e end # # Returns true if there is a FlowExpression stored with the given id. # def has_key? (fei) (Expression.find_by_fei(fei.to_s) != nil) end # # Deletes a flow expression. # def delete (fei) synchronize do Expression.delete_all ["fei = ?", fei.to_s] end end # # Returns the count of expressions currently stored. # def size Expression.count end alias :length :size # # Danger ! Will remove all the expressions in the database. # def purge Expression.delete_all end # # Given an expression class (Schedulable or ParticipantExpression for # example), calls the passed block for each expression of that class. # def each_of_kind (kind, &block) classes = get_expression_map.get_expression_classes(kind) classes = classes.collect { |c| c.name } exps = Expression.find_all_by_exp_class(classes) exp_each exps, &block end # # Calls the block for each expression stored. If a wfid prefix is # passed, only the expressions whose workflow instance id begins # with it will be iterated over. # def each (wfid_prefix=nil, &block) params = {} params[:conditions] = [ "wfid LIKE ?", "#{wfid_prefix}%" ] \ if wfid_prefix exps = Expression.find(:all, params) exp_each exps, &block end alias :real_each :each protected # # Used by each() and each_of_kind(). # def exp_each (expressions, &block) expressions.each do |exp| fexp = as_owfe_expression(exp) block.call fexp.fei, fexp end end # # Extracts the OpenWFE FlowExpression instance from the # active record and makes sure its application_context is set. # def as_owfe_expression (record) fe = record.svalue fe.application_context = @application_context fe end end # # A DbExpressionStorage that does less work, for more performance, # thanks to the ThreadedStorageMixin. # class ThreadedDbExpressionStorage < DbExpressionStorage include OpenWFE::ThreadedStorageMixin def initialize (service_name, application_context) super start_processing_thread() # # which sets @thread_id end end end