dynflow 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.travis.yml +9 -0
- data/Gemfile +0 -10
- data/MIT-LICENSE +1 -1
- data/README.md +99 -37
- data/Rakefile +2 -6
- data/doc/images/logo.png +0 -0
- data/dynflow.gemspec +10 -1
- data/examples/generate_work_for_daemon.rb +24 -0
- data/examples/orchestrate.rb +121 -0
- data/examples/run_daemon.rb +17 -0
- data/examples/web_console.rb +29 -0
- data/lib/dynflow.rb +27 -6
- data/lib/dynflow/action.rb +185 -77
- data/lib/dynflow/action/cancellable_polling.rb +18 -0
- data/lib/dynflow/action/finalize_phase.rb +18 -0
- data/lib/dynflow/action/flow_phase.rb +44 -0
- data/lib/dynflow/action/format.rb +46 -0
- data/lib/dynflow/action/missing.rb +26 -0
- data/lib/dynflow/action/plan_phase.rb +85 -0
- data/lib/dynflow/action/polling.rb +49 -0
- data/lib/dynflow/action/presenter.rb +51 -0
- data/lib/dynflow/action/progress.rb +62 -0
- data/lib/dynflow/action/run_phase.rb +43 -0
- data/lib/dynflow/action/suspended.rb +21 -0
- data/lib/dynflow/clock.rb +133 -0
- data/lib/dynflow/daemon.rb +29 -0
- data/lib/dynflow/execution_plan.rb +285 -33
- data/lib/dynflow/execution_plan/dependency_graph.rb +29 -0
- data/lib/dynflow/execution_plan/output_reference.rb +52 -0
- data/lib/dynflow/execution_plan/steps.rb +12 -0
- data/lib/dynflow/execution_plan/steps/abstract.rb +121 -0
- data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +52 -0
- data/lib/dynflow/execution_plan/steps/error.rb +33 -0
- data/lib/dynflow/execution_plan/steps/finalize_step.rb +23 -0
- data/lib/dynflow/execution_plan/steps/plan_step.rb +81 -0
- data/lib/dynflow/execution_plan/steps/run_step.rb +21 -0
- data/lib/dynflow/executors.rb +9 -0
- data/lib/dynflow/executors/abstract.rb +32 -0
- data/lib/dynflow/executors/parallel.rb +88 -0
- data/lib/dynflow/executors/parallel/core.rb +119 -0
- data/lib/dynflow/executors/parallel/execution_plan_manager.rb +120 -0
- data/lib/dynflow/executors/parallel/flow_manager.rb +48 -0
- data/lib/dynflow/executors/parallel/pool.rb +102 -0
- data/lib/dynflow/executors/parallel/running_steps_manager.rb +63 -0
- data/lib/dynflow/executors/parallel/sequence_cursor.rb +97 -0
- data/lib/dynflow/executors/parallel/sequential_manager.rb +81 -0
- data/lib/dynflow/executors/parallel/work_queue.rb +44 -0
- data/lib/dynflow/executors/parallel/worker.rb +30 -0
- data/lib/dynflow/executors/remote_via_socket.rb +38 -0
- data/lib/dynflow/executors/remote_via_socket/core.rb +150 -0
- data/lib/dynflow/flows.rb +13 -0
- data/lib/dynflow/flows/abstract.rb +36 -0
- data/lib/dynflow/flows/abstract_composed.rb +104 -0
- data/lib/dynflow/flows/atom.rb +36 -0
- data/lib/dynflow/flows/concurrence.rb +28 -0
- data/lib/dynflow/flows/sequence.rb +13 -0
- data/lib/dynflow/future.rb +173 -0
- data/lib/dynflow/listeners.rb +7 -0
- data/lib/dynflow/listeners/abstract.rb +13 -0
- data/lib/dynflow/listeners/serialization.rb +41 -0
- data/lib/dynflow/listeners/socket.rb +88 -0
- data/lib/dynflow/logger_adapters.rb +8 -0
- data/lib/dynflow/logger_adapters/abstract.rb +30 -0
- data/lib/dynflow/logger_adapters/delegator.rb +13 -0
- data/lib/dynflow/logger_adapters/formatters.rb +8 -0
- data/lib/dynflow/logger_adapters/formatters/abstract.rb +33 -0
- data/lib/dynflow/logger_adapters/formatters/exception.rb +15 -0
- data/lib/dynflow/logger_adapters/simple.rb +59 -0
- data/lib/dynflow/micro_actor.rb +102 -0
- data/lib/dynflow/persistence.rb +53 -0
- data/lib/dynflow/persistence_adapters.rb +6 -0
- data/lib/dynflow/persistence_adapters/abstract.rb +56 -0
- data/lib/dynflow/persistence_adapters/sequel.rb +160 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/001_initial.rb +52 -0
- data/lib/dynflow/serializable.rb +66 -0
- data/lib/dynflow/simple_world.rb +18 -0
- data/lib/dynflow/stateful.rb +40 -0
- data/lib/dynflow/testing.rb +32 -0
- data/lib/dynflow/testing/assertions.rb +64 -0
- data/lib/dynflow/testing/dummy_execution_plan.rb +40 -0
- data/lib/dynflow/testing/dummy_executor.rb +29 -0
- data/lib/dynflow/testing/dummy_planned_action.rb +18 -0
- data/lib/dynflow/testing/dummy_step.rb +19 -0
- data/lib/dynflow/testing/dummy_world.rb +33 -0
- data/lib/dynflow/testing/factories.rb +83 -0
- data/lib/dynflow/testing/managed_clock.rb +23 -0
- data/lib/dynflow/testing/mimic.rb +38 -0
- data/lib/dynflow/transaction_adapters.rb +9 -0
- data/lib/dynflow/transaction_adapters/abstract.rb +26 -0
- data/lib/dynflow/transaction_adapters/active_record.rb +27 -0
- data/lib/dynflow/transaction_adapters/none.rb +12 -0
- data/lib/dynflow/version.rb +1 -1
- data/lib/dynflow/web_console.rb +277 -0
- data/lib/dynflow/world.rb +168 -0
- data/test/action_test.rb +89 -11
- data/test/clock_test.rb +59 -0
- data/test/code_workflow_example.rb +382 -0
- data/test/execution_plan_test.rb +195 -64
- data/test/executor_test.rb +692 -0
- data/test/persistance_adapters_test.rb +173 -0
- data/test/test_helper.rb +316 -1
- data/test/testing_test.rb +148 -0
- data/test/web_console_test.rb +38 -0
- data/web/assets/javascripts/application.js +25 -0
- data/web/assets/stylesheets/application.css +101 -0
- data/web/assets/vendor/bootstrap/css/bootstrap-responsive.css +1109 -0
- data/web/assets/vendor/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/web/assets/vendor/bootstrap/css/bootstrap.css +6167 -0
- data/web/assets/vendor/bootstrap/css/bootstrap.min.css +9 -0
- data/web/assets/vendor/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/web/assets/vendor/bootstrap/img/glyphicons-halflings.png +0 -0
- data/web/assets/vendor/bootstrap/js/bootstrap.js +2280 -0
- data/web/assets/vendor/bootstrap/js/bootstrap.min.js +6 -0
- data/web/assets/vendor/google-code-prettify/lang-basic.js +3 -0
- data/web/assets/vendor/google-code-prettify/prettify.css +1 -0
- data/web/assets/vendor/google-code-prettify/prettify.js +30 -0
- data/web/assets/vendor/google-code-prettify/run_prettify.js +34 -0
- data/web/assets/vendor/jquery/jquery.js +9807 -0
- data/web/views/flow.erb +19 -0
- data/web/views/flow_step.erb +31 -0
- data/web/views/index.erb +39 -0
- data/web/views/layout.erb +20 -0
- data/web/views/plan_step.erb +11 -0
- data/web/views/show.erb +54 -0
- metadata +250 -11
- data/examples/events.rb +0 -71
- data/examples/workflow.rb +0 -140
- data/lib/dynflow/bus.rb +0 -168
- data/lib/dynflow/dispatcher.rb +0 -36
- data/lib/dynflow/logger.rb +0 -34
- data/lib/dynflow/step.rb +0 -234
- data/test/bus_test.rb +0 -150
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module Dynflow
|
|
2
|
+
module Listeners
|
|
3
|
+
class Socket < Abstract
|
|
4
|
+
# TODO terminate when exiting
|
|
5
|
+
include Listeners::Serialization
|
|
6
|
+
include Algebrick::Matching
|
|
7
|
+
|
|
8
|
+
def initialize(world, socket_path)
|
|
9
|
+
super(world)
|
|
10
|
+
|
|
11
|
+
File.delete socket_path if File.exist? socket_path
|
|
12
|
+
@server = UNIXServer.new socket_path
|
|
13
|
+
File.chmod(0600, socket_path)
|
|
14
|
+
|
|
15
|
+
@clients = []
|
|
16
|
+
@client_barriers = {}
|
|
17
|
+
@loop = Thread.new { loop { listen } }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def listen
|
|
23
|
+
ios = [@server, *@clients]
|
|
24
|
+
reads, writes, errors = IO.select(ios, [], ios)
|
|
25
|
+
reads.each do |readable|
|
|
26
|
+
if readable == @server
|
|
27
|
+
add_client @server.accept
|
|
28
|
+
logger.info 'Client connected.'
|
|
29
|
+
|
|
30
|
+
else
|
|
31
|
+
match message = receive_message(readable),
|
|
32
|
+
(on ~Execute do |(id, uuid)|
|
|
33
|
+
execute(readable, id, uuid)
|
|
34
|
+
end),
|
|
35
|
+
(on NilClass.to_m do
|
|
36
|
+
remove_client readable
|
|
37
|
+
logger.info 'Client disconnected.'
|
|
38
|
+
end)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
rescue => error
|
|
42
|
+
logger.fatal error
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def execute(readable, id, uuid)
|
|
46
|
+
responded = false
|
|
47
|
+
respond = -> error = nil do
|
|
48
|
+
unless responded
|
|
49
|
+
responded = true
|
|
50
|
+
send_message_to_client(readable, if error
|
|
51
|
+
logger.error error
|
|
52
|
+
Failed[id, error.message]
|
|
53
|
+
else
|
|
54
|
+
Accepted[id]
|
|
55
|
+
end)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@world.execute(uuid,
|
|
60
|
+
f = Future.new do |_|
|
|
61
|
+
if f.resolved?
|
|
62
|
+
respond.call
|
|
63
|
+
send_message_to_client readable, Done[id, uuid]
|
|
64
|
+
else
|
|
65
|
+
respond.call f.value
|
|
66
|
+
end
|
|
67
|
+
end)
|
|
68
|
+
respond.call
|
|
69
|
+
rescue Dynflow::Error => e
|
|
70
|
+
respond.call e
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def add_client(client)
|
|
74
|
+
@clients << client
|
|
75
|
+
@client_barriers[client] = Mutex.new
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def remove_client(client)
|
|
79
|
+
@clients.delete client
|
|
80
|
+
@client_barriers.delete client
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def send_message_to_client(client, message)
|
|
84
|
+
send_message client, message, @client_barriers[client]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Dynflow
|
|
2
|
+
module LoggerAdapters
|
|
3
|
+
class Abstract
|
|
4
|
+
|
|
5
|
+
# @returns [#fatal, #error, #warn, #info, #debug] logger object for logging errors from action execution
|
|
6
|
+
def action_logger
|
|
7
|
+
raise NotImplementedError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @returns [#fatal, #error, #warn, #info, #debug] logger object for logging Dynflow errors
|
|
11
|
+
def dynflow_logger
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def level
|
|
16
|
+
raise NotImplementedError
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def level=(v)
|
|
20
|
+
raise NotImplementedError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def apply_formatters(base, formatters)
|
|
26
|
+
formatters.reduce(base) { |base, formatter| formatter.new(base) }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Dynflow
|
|
2
|
+
module LoggerAdapters
|
|
3
|
+
class Delegator < Abstract
|
|
4
|
+
|
|
5
|
+
attr_reader :action_logger, :dynflow_logger
|
|
6
|
+
|
|
7
|
+
def initialize(action_logger, dynflow_logger, formatters = [Formatters::Exception])
|
|
8
|
+
@action_logger = apply_formatters action_logger, formatters
|
|
9
|
+
@dynflow_logger = apply_formatters dynflow_logger, formatters
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Dynflow
|
|
2
|
+
module LoggerAdapters
|
|
3
|
+
module Formatters
|
|
4
|
+
class Abstract
|
|
5
|
+
def initialize(base)
|
|
6
|
+
@base = base
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
[:fatal, :error, :warn, :info, :debug].each do |method|
|
|
10
|
+
define_method method do |message, &block|
|
|
11
|
+
if block
|
|
12
|
+
@base.send method, &-> { format(block.call) }
|
|
13
|
+
else
|
|
14
|
+
@base.send method, format(message)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def level=(v)
|
|
20
|
+
@base.level = v
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def level
|
|
24
|
+
@base.level
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def format(message)
|
|
28
|
+
raise NotImplementedError
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Dynflow
|
|
2
|
+
module LoggerAdapters
|
|
3
|
+
module Formatters
|
|
4
|
+
class Exception < Abstract
|
|
5
|
+
def format(message)
|
|
6
|
+
if ::Exception === message
|
|
7
|
+
"#{message.message} (#{message.class})\n#{message.backtrace.join("\n")}"
|
|
8
|
+
else
|
|
9
|
+
message
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'English'
|
|
2
|
+
|
|
3
|
+
module Dynflow
|
|
4
|
+
module LoggerAdapters
|
|
5
|
+
class Simple < Abstract
|
|
6
|
+
require 'logger'
|
|
7
|
+
|
|
8
|
+
attr_reader :logger, :action_logger, :dynflow_logger
|
|
9
|
+
|
|
10
|
+
def initialize(output = $stdout, level = Logger::DEBUG, formatters = [Formatters::Exception])
|
|
11
|
+
@logger = Logger.new(output)
|
|
12
|
+
@logger.level = level
|
|
13
|
+
@logger.formatter = method(:formatter).to_proc
|
|
14
|
+
@action_logger = apply_formatters ProgNameWrapper.new(@logger, ' action'), formatters
|
|
15
|
+
@dynflow_logger = apply_formatters ProgNameWrapper.new(@logger, 'dynflow'), formatters
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def level
|
|
19
|
+
@logger.level
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def level=(v)
|
|
23
|
+
@logger.level = v
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def formatter(severity, datetime, prog_name, msg)
|
|
29
|
+
format "[%s #%d] %5s -- %s%s\n",
|
|
30
|
+
datetime.strftime('%Y-%m-%d %H:%M:%S.%L'),
|
|
31
|
+
$PID,
|
|
32
|
+
severity,
|
|
33
|
+
(prog_name ? prog_name + ': ' : ''),
|
|
34
|
+
msg.to_s
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class ProgNameWrapper
|
|
38
|
+
def initialize(logger, prog_name)
|
|
39
|
+
@logger = logger
|
|
40
|
+
@prog_name = prog_name
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
{ fatal: 4, error: 3, warn: 2, info: 1, debug: 0 }.each do |method, level|
|
|
44
|
+
define_method method do |message, &block|
|
|
45
|
+
@logger.add level, message, @prog_name, &block
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def level=(v)
|
|
50
|
+
@logger.level = v
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def level
|
|
54
|
+
@logger.level
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module Dynflow
|
|
2
|
+
class MicroActor
|
|
3
|
+
include Algebrick::TypeCheck
|
|
4
|
+
include Algebrick::Matching
|
|
5
|
+
|
|
6
|
+
attr_reader :logger, :initialized
|
|
7
|
+
|
|
8
|
+
Terminate = Algebrick.atom
|
|
9
|
+
|
|
10
|
+
def initialize(logger, *args)
|
|
11
|
+
@logger = logger
|
|
12
|
+
@initialized = Future.new
|
|
13
|
+
@thread = Thread.new { run *args }
|
|
14
|
+
Thread.pass until @mailbox
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def <<(message)
|
|
18
|
+
raise 'actor terminated' if terminated?
|
|
19
|
+
@mailbox << [message, nil]
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def ask(message, future = Future.new)
|
|
24
|
+
future.fail Dynflow::Error.new('actor terminated') if terminated?
|
|
25
|
+
@mailbox << [message, future]
|
|
26
|
+
future
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def stopped?
|
|
30
|
+
@terminated.ready?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def delayed_initialize(*args)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def termination
|
|
39
|
+
terminate!
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def terminating?
|
|
43
|
+
@terminated
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def terminated?
|
|
47
|
+
terminating? && @terminated.ready?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def terminate!
|
|
51
|
+
raise unless Thread.current == @thread
|
|
52
|
+
@terminated.resolve true
|
|
53
|
+
throw Terminate
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def on_message(message)
|
|
57
|
+
raise NotImplementedError
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def receive
|
|
61
|
+
message, future = @mailbox.pop
|
|
62
|
+
#logger.debug "#{self.class} received:\n #{message}"
|
|
63
|
+
if message == Terminate
|
|
64
|
+
# TODO do not use this future to store in @terminated use one added to Terminate message
|
|
65
|
+
if terminating?
|
|
66
|
+
@terminated.do_then { future.resolve true } if future
|
|
67
|
+
else
|
|
68
|
+
@terminated = (future || Future.new)
|
|
69
|
+
termination
|
|
70
|
+
end
|
|
71
|
+
else
|
|
72
|
+
on_envelope message, future
|
|
73
|
+
end
|
|
74
|
+
rescue => error
|
|
75
|
+
logger.fatal error
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def on_envelope(message, future)
|
|
79
|
+
if future
|
|
80
|
+
future.evaluate_to { on_message message }
|
|
81
|
+
else
|
|
82
|
+
on_message message
|
|
83
|
+
end
|
|
84
|
+
if future && future.failed?
|
|
85
|
+
logger.error future.value
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def run(*args)
|
|
90
|
+
Thread.current.abort_on_exception = true
|
|
91
|
+
|
|
92
|
+
@mailbox = Queue.new
|
|
93
|
+
@terminated = nil
|
|
94
|
+
|
|
95
|
+
delayed_initialize(*args)
|
|
96
|
+
Thread.pass until @initialized
|
|
97
|
+
@initialized.resolve true
|
|
98
|
+
|
|
99
|
+
catch(Terminate) { loop { receive } }
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'dynflow/persistence_adapters'
|
|
2
|
+
|
|
3
|
+
module Dynflow
|
|
4
|
+
|
|
5
|
+
class Persistence
|
|
6
|
+
|
|
7
|
+
attr_reader :adapter
|
|
8
|
+
|
|
9
|
+
def initialize(world, persistence_adapter)
|
|
10
|
+
@world = world
|
|
11
|
+
@adapter = persistence_adapter
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def load_action(step)
|
|
15
|
+
attributes = adapter.
|
|
16
|
+
load_action(step.execution_plan_id, step.action_id).
|
|
17
|
+
update(step: step)
|
|
18
|
+
return Action.from_hash(attributes,
|
|
19
|
+
step.phase,
|
|
20
|
+
step,
|
|
21
|
+
step.world)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def save_action(execution_plan_id, action)
|
|
25
|
+
adapter.save_action(execution_plan_id, action.id, action.to_hash)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def find_execution_plans(options)
|
|
29
|
+
adapter.find_execution_plans(options).map do |execution_plan_hash|
|
|
30
|
+
ExecutionPlan.new_from_hash(execution_plan_hash, @world)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load_execution_plan(id)
|
|
35
|
+
execution_plan_hash = adapter.load_execution_plan(id)
|
|
36
|
+
ExecutionPlan.new_from_hash(execution_plan_hash, @world)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def save_execution_plan(execution_plan)
|
|
40
|
+
adapter.save_execution_plan(execution_plan.id, execution_plan.to_hash)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def load_step(execution_plan_id, step_id, world)
|
|
44
|
+
step_hash = adapter.load_step(execution_plan_id, step_id)
|
|
45
|
+
ExecutionPlan::Steps::Abstract.from_hash(step_hash, execution_plan_id, world)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def save_step(step)
|
|
49
|
+
adapter.save_step(step.execution_plan_id, step.id, step.to_hash)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Dynflow
|
|
2
|
+
module PersistenceAdapters
|
|
3
|
+
class Abstract
|
|
4
|
+
def pagination?
|
|
5
|
+
false
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def filtering_by
|
|
9
|
+
[]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def ordering_by
|
|
13
|
+
[]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @option options [Integer] page index of the page (starting at 0)
|
|
17
|
+
# @option options [Integer] per_page the number of the items on page
|
|
18
|
+
# @option options [Symbol] order_by name of the column to use for ordering
|
|
19
|
+
# @option options [true, false] desc set to true if order should be descending
|
|
20
|
+
# @option options [Hash{ Symbol => Object,Array<object> }] filters hash represents
|
|
21
|
+
# set of allowed values for a given key representing column
|
|
22
|
+
def find_execution_plans(options = {})
|
|
23
|
+
raise NotImplementedError
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def load_execution_plan(execution_plan_id)
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def save_execution_plan(execution_plan_id, value)
|
|
31
|
+
raise NotImplementedError
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load_step(execution_plan_id, step_id)
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def save_step(execution_plan_id, step_id, value)
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def load_action(execution_plan_id, action_id)
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def save_action(execution_plan_id, action_id, value)
|
|
47
|
+
raise NotImplementedError
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# for debug purposes
|
|
51
|
+
def to_hash
|
|
52
|
+
raise NotImplementedError
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|