Class: BatchKit::Definable Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/batch-kit/framework/definable.rb

Overview

This class is abstract.

Captures details of a definable batch process, e.g. a Task or Job.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeDefinable

Create a new instance of this definition.



69
70
71
# File 'lib/batch-kit/framework/definable.rb', line 69

def initialize
    @runs = []
end

Instance Attribute Details

#:description(: description) ⇒ Object (readonly)

A short description of what this process does.



63
64
65
# File 'lib/batch-kit/framework/definable.rb', line 63

add_properties(:name, :description, :instance, :runs,
    :lock_name, :lock_timeout, :lock_wait_timeout
)

#:instance(: instance) ⇒ Object (readonly)

An optional expression used to assign an instance identifier to a process. An instance identifier allows a process that has different execution profiles (typically depending on the arguments it is run with) to identify which of those profiles it is executing. This expression will be evaluated at the time this process is invoked, and the result will become the instance identifier for the Runnable.



63
64
65
# File 'lib/batch-kit/framework/definable.rb', line 63

add_properties(:name, :description, :instance, :runs,
    :lock_name, :lock_timeout, :lock_wait_timeout
)

#:lock_name(: lock_name) ⇒ Object (readonly)

The name of any lock that this process requires before it can proceed. If nil, no lock is required and the process can commence without any co-ordination with other processes.



63
64
65
# File 'lib/batch-kit/framework/definable.rb', line 63

add_properties(:name, :description, :instance, :runs,
    :lock_name, :lock_timeout, :lock_wait_timeout
)

#:name(: name) ⇒ Object (readonly)

A user-friendly name for this process.



63
64
65
# File 'lib/batch-kit/framework/definable.rb', line 63

add_properties(:name, :description, :instance, :runs,
    :lock_name, :lock_timeout, :lock_wait_timeout
)

#:runs(: runs) ⇒ Object (readonly)

Array of runs of this process.



63
64
65
# File 'lib/batch-kit/framework/definable.rb', line 63

add_properties(:name, :description, :instance, :runs,
    :lock_name, :lock_timeout, :lock_wait_timeout
)

Class Method Details

.add_properties(*props) ⇒ Object

Register additional properties to be recorded on this definable.

Parameters:

  • props (Array<Symbol>)

    The names of properties to be added to the definition. Used by sub-classes to add to the available properties. This provides a mechanism by which associated Run objects can obtain a list of process properties that they can delegate.



17
18
19
20
# File 'lib/batch-kit/framework/definable.rb', line 17

def add_properties(*props)
    attr_accessor(*props)
    properties.concat(props)
end

.inherited(subclass) ⇒ Object

When this class is inherited, we need to copy the common property names into the sub-class, since each sub-class needs the common property names defined on this base class, as well as any sub- class specific properties.



34
35
36
# File 'lib/batch-kit/framework/definable.rb', line 34

def inherited(subclass)
    subclass.instance_variable_set(:@properties, @properties.clone)
end

.propertiesArray<Symbol>

Returns the names of properties available on this definition.

Returns:

  • (Array<Symbol>)

    the names of properties available on this definition.



25
26
27
# File 'lib/batch-kit/framework/definable.rb', line 25

def properties
    @properties ||= []
end

Instance Method Details

#:lock_timeout=(: lock_timeout=(value)) ⇒ Object

Number of seconds after which a lock obtained by this process will expire. This is to ensure that locks don’t remain indefinitely if a process fails to release the lock properly. As such, it should be longer than any reasonable run of this process is likely to take, but no longer.



63
64
65
# File 'lib/batch-kit/framework/definable.rb', line 63

add_properties(:name, :description, :instance, :runs,
    :lock_name, :lock_timeout, :lock_wait_timeout
)

#:lock_wait_timeout=(: lock_wait_timeout=(value)) ⇒ Object

Number of seconds before this process will give up waiting for a lock to become available.



63
64
65
# File 'lib/batch-kit/framework/definable.rb', line 63

add_properties(:name, :description, :instance, :runs,
    :lock_name, :lock_timeout, :lock_wait_timeout
)

#add_aspect(tgt_class, mthd_name) ⇒ Object

Adds an aspect (as in aspect-oriented programming, or AOP) around the existing instance method mthd_name on tgt_class. The aspect does the following:

  • Calls the #pre_execute method with the object instance on which the aspect method is being invoked. If the #pre_execute method returns false, the method call is skipped; otherwise, proceeds to the next step.

  • Calls the #around_execute method, which must yield back at the point at which the wrapped method body should be invoked.

  • Calls the #post_execute method with a boolean OK indicator, and the result of the method (if OK) or the exception it threw (if not OK).

Parameters:

  • tgt_class (Class)

    The class on which the method to be wrapped is defined.

  • mthd_name (Symbol)

    The name of the instance method to be wrapped.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/batch-kit/framework/definable.rb', line 116

def add_aspect(tgt_class, mthd_name)
    defn = self
    mthd = tgt_class.instance_method(mthd_name)
    tgt_class.class_eval do
        define_method mthd_name do |*args, &block|
            run = defn.create_run(self, *args)
            if run.pre_execute(self, *args)
                ok = false
                result = nil
                begin
                    run.around_execute(self, *args) do
                        result = mthd.bind(self).call(*args, &block)
                    end
                    ok = true
                    run.success(self, result)
                    result
                rescue Exception => ex
                    run.failure(self, ex) unless ok
                    raise
                rescue Interrupt
                    run.abort(self) unless ok
                    raise
                ensure
                    run.post_execute(self, ok)
                end
            end
        end
    end
    Events.publish(tgt_class, event_name('defined'), mthd_name)
end

#create_run(process_obj, *args) ⇒ Object

Creates an associated Runnable object for this definition. This method must be overridden in sub-classes.

Parameters:

  • process_obj (Object)

    The process object instance on which the process method will be invoked.

  • args (Array<Object>)

    The arguments to be passed to the process method.



155
156
157
# File 'lib/batch-kit/framework/definable.rb', line 155

def create_run(process_obj, *args)
    raise "Not implemented in #{self.class.name}"
end

#event_name(event) ⇒ Object

Returns an event name for publication, based on the sub-class of Runnable that is triggering the event.



76
77
78
# File 'lib/batch-kit/framework/definable.rb', line 76

def event_name(event)
    "#{self.class.name.split('::')[1].downcase}.#{event}"
end

#set_from_options(opts) ⇒ Object

Sets properties from an options hash.

Parameters:

  • opts (Hash)

    A hash containing properties to be set on this definable.



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/batch-kit/framework/definable.rb', line 85

def set_from_options(opts)
    unknown = opts.keys - self.class.properties
    if unknown.size > 0
        raise ArgumentError, "The following option(s) are invalid for #{
            self.class.name}: #{unknown.join(', ')}. Valid options are: #{
            self.class.properties.join(', ')}"
    end
    self.class.properties.each do |prop|
        if opts.has_key?(prop)
            self.send("#{prop}=", opts[prop])
        end
    end
end