dynflow 1.4.7 → 1.6.1

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/{test/prepare_travis_env.sh → .github/install_dependencies.sh} +2 -2
  3. data/.github/workflows/ruby.yml +116 -0
  4. data/dynflow.gemspec +1 -0
  5. data/examples/chunked_output_benchmark.rb +77 -0
  6. data/extras/expand/main.go +180 -0
  7. data/lib/dynflow/action/suspended.rb +4 -4
  8. data/lib/dynflow/action/timeouts.rb +2 -2
  9. data/lib/dynflow/action.rb +15 -4
  10. data/lib/dynflow/actor.rb +20 -4
  11. data/lib/dynflow/clock.rb +2 -2
  12. data/lib/dynflow/delayed_executors/abstract_core.rb +11 -9
  13. data/lib/dynflow/director/running_steps_manager.rb +2 -2
  14. data/lib/dynflow/director.rb +42 -5
  15. data/lib/dynflow/dispatcher/client_dispatcher.rb +8 -2
  16. data/lib/dynflow/dispatcher/executor_dispatcher.rb +12 -2
  17. data/lib/dynflow/dispatcher.rb +7 -2
  18. data/lib/dynflow/execution_history.rb +1 -1
  19. data/lib/dynflow/execution_plan/hooks.rb +1 -1
  20. data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +1 -0
  21. data/lib/dynflow/execution_plan.rb +16 -5
  22. data/lib/dynflow/executors/abstract/core.rb +10 -1
  23. data/lib/dynflow/executors/parallel.rb +6 -2
  24. data/lib/dynflow/extensions/msgpack.rb +41 -0
  25. data/lib/dynflow/extensions.rb +6 -0
  26. data/lib/dynflow/flows/abstract.rb +14 -0
  27. data/lib/dynflow/flows/abstract_composed.rb +2 -7
  28. data/lib/dynflow/flows/atom.rb +2 -2
  29. data/lib/dynflow/flows/concurrence.rb +2 -0
  30. data/lib/dynflow/flows/registry.rb +32 -0
  31. data/lib/dynflow/flows/sequence.rb +2 -0
  32. data/lib/dynflow/flows.rb +1 -0
  33. data/lib/dynflow/persistence.rb +10 -0
  34. data/lib/dynflow/persistence_adapters/sequel.rb +51 -16
  35. data/lib/dynflow/persistence_adapters/sequel_migrations/021_create_output_chunks.rb +30 -0
  36. data/lib/dynflow/persistence_adapters/sequel_migrations/022_store_flows_as_msgpack.rb +90 -0
  37. data/lib/dynflow/persistence_adapters/sequel_migrations/023_sqlite_workarounds.rb +19 -0
  38. data/lib/dynflow/serializable.rb +2 -2
  39. data/lib/dynflow/testing/dummy_coordinator.rb +10 -0
  40. data/lib/dynflow/testing/dummy_planned_action.rb +4 -0
  41. data/lib/dynflow/testing/dummy_world.rb +2 -1
  42. data/lib/dynflow/testing/in_thread_executor.rb +2 -2
  43. data/lib/dynflow/testing/in_thread_world.rb +5 -5
  44. data/lib/dynflow/testing.rb +1 -0
  45. data/lib/dynflow/version.rb +1 -1
  46. data/lib/dynflow/world.rb +16 -4
  47. data/lib/dynflow.rb +2 -1
  48. data/test/dispatcher_test.rb +6 -0
  49. data/test/execution_plan_hooks_test.rb +36 -0
  50. data/test/extensions_test.rb +42 -0
  51. data/test/flows_test.rb +44 -0
  52. data/test/future_execution_test.rb +6 -3
  53. data/test/persistence_test.rb +2 -2
  54. data/web/views/flow_step.erb +1 -0
  55. metadata +34 -8
  56. data/.travis.yml +0 -33
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ Sequel.migration do
3
+ up do
4
+ type = database_type
5
+ create_table(:dynflow_output_chunks) do
6
+ primary_key :id
7
+
8
+ column_properties = if type.to_s.include?('postgres')
9
+ {type: :uuid}
10
+ else
11
+ {type: String, size: 36, fixed: true, null: false}
12
+ end
13
+ foreign_key :execution_plan_uuid, :dynflow_execution_plans, **column_properties
14
+ index :execution_plan_uuid
15
+
16
+ column :action_id, Integer, null: false
17
+ foreign_key [:execution_plan_uuid, :action_id], :dynflow_actions,
18
+ name: :dynflow_output_chunks_execution_plan_uuid_fkey1
19
+ index [:execution_plan_uuid, :action_id]
20
+
21
+ column :chunk, String, text: true
22
+ column :kind, String
23
+ column :timestamp, Time, null: false
24
+ end
25
+ end
26
+
27
+ down do
28
+ drop_table(:dynflow_output_chunks)
29
+ end
30
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'multi_json'
4
+ require 'msgpack'
5
+
6
+ def table_pkeys(table)
7
+ case table
8
+ when :dynflow_execution_plans
9
+ [:uuid]
10
+ when :dynflow_actions, :dynflow_steps
11
+ [:execution_plan_uuid, :id]
12
+ when :dynflow_coordinator_records
13
+ [:id, :class]
14
+ when :dynflow_delayed_plans
15
+ [:execution_plan_uuid]
16
+ when :dynflow_envelopes
17
+ [:id]
18
+ when :dynflow_output_chunks
19
+ [:chunk]
20
+ else
21
+ raise "Unknown table '#{table}'"
22
+ end
23
+ end
24
+
25
+ def conditions_for_row(table, row)
26
+ row.slice(*table_pkeys(table))
27
+ end
28
+
29
+ def migrate_table(table, from_names, to_names, new_type)
30
+ alter_table(table) do
31
+ to_names.each do |new|
32
+ add_column new, new_type
33
+ end
34
+ end
35
+
36
+ relevant_columns = table_pkeys(table) | from_names
37
+
38
+ from(table).select(*relevant_columns).each do |row|
39
+ update = from_names.zip(to_names).reduce({}) do |acc, (from, to)|
40
+ row[from].nil? ? acc : acc.merge(to => yield(row[from]))
41
+ end
42
+ next if update.empty?
43
+ from(table).where(conditions_for_row(table, row)).update(update)
44
+ end
45
+
46
+ from_names.zip(to_names).each do |old, new|
47
+ alter_table(table) do
48
+ drop_column old
49
+ end
50
+
51
+ if database_type == :mysql
52
+ type = new_type == File ? 'blob' : 'mediumtext'
53
+ run "ALTER TABLE #{table} CHANGE COLUMN `#{new}` `#{old}` #{type};"
54
+ else
55
+ rename_column table, new, old
56
+ end
57
+ end
58
+ end
59
+
60
+ Sequel.migration do
61
+
62
+ TABLES = {
63
+ :dynflow_actions => [:data, :input, :output],
64
+ :dynflow_coordinator_records => [:data],
65
+ :dynflow_delayed_plans => [:serialized_args, :data],
66
+ :dynflow_envelopes => [:data],
67
+ :dynflow_execution_plans => [:run_flow, :finalize_flow, :execution_history, :step_ids],
68
+ :dynflow_steps => [:error, :children],
69
+ :dynflow_output_chunks => [:chunk]
70
+ }
71
+
72
+ up do
73
+ TABLES.each do |table, columns|
74
+ new_columns = columns.map { |c| "#{c}_blob" }
75
+
76
+ migrate_table table, columns, new_columns, File do |data|
77
+ ::Sequel.blob(MessagePack.pack(MultiJson.load(data)))
78
+ end
79
+ end
80
+ end
81
+
82
+ down do
83
+ TABLES.each do |table, columns|
84
+ new_columns = columns.map { |c| c + '_text' }
85
+ migrate_table table, columns, new_columns, String do |data|
86
+ MultiJson.dump(MessagePack.unpack(data))
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ tables = [:dynflow_actions, :dynflow_delayed_plans, :dynflow_steps, :dynflow_output_chunks]
3
+ Sequel.migration do
4
+ up do
5
+ if database_type == :sqlite && Gem::Version.new(SQLite3::SQLITE_VERSION) <= Gem::Version.new('3.7.17')
6
+ tables.each do |table|
7
+ alter_table(table) { drop_foreign_key [:execution_plan_uuid] }
8
+ end
9
+ end
10
+ end
11
+
12
+ down do
13
+ if database_type == :sqlite && Gem::Version.new(SQLite3::SQLITE_VERSION) <= Gem::Version.new('3.7.17')
14
+ tables.each do |table|
15
+ alter_table(table) { add_foreign_key [:execution_plan_uuid], :dynflow_execution_plans }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -45,12 +45,12 @@ module Dynflow
45
45
  if values.size == 1
46
46
  value = values.first
47
47
  case value
48
- when String, Numeric, Symbol, TrueClass, FalseClass, NilClass, Time
49
- value
50
48
  when Hash
51
49
  value.inject({}) { |h, (k, v)| h.update k => recursive_to_hash(v) }
52
50
  when Array
53
51
  value.map { |v| recursive_to_hash v }
52
+ when ->(v) { v.respond_to?(:to_msgpack) }
53
+ value
54
54
  else
55
55
  value.to_hash
56
56
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ module Dynflow
3
+ module Testing
4
+ class DummyCoordinator
5
+ def find_records(*args)
6
+ []
7
+ end
8
+ end
9
+ end
10
+ end
@@ -15,6 +15,10 @@ module Dynflow
15
15
  @plan_input = args
16
16
  self
17
17
  end
18
+
19
+ def run_step_id
20
+ @run_step_id ||= Testing.get_id
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -5,7 +5,7 @@ module Dynflow
5
5
  extend Mimic
6
6
  mimic! World
7
7
 
8
- attr_reader :clock, :executor, :middleware
8
+ attr_reader :clock, :executor, :middleware, :coordinator
9
9
  attr_accessor :action
10
10
 
11
11
  def initialize(_config = nil)
@@ -13,6 +13,7 @@ module Dynflow
13
13
  @clock = ManagedClock.new
14
14
  @executor = DummyExecutor.new(self)
15
15
  @middleware = Middleware::World.new
16
+ @coordinator = DummyCoordinator.new
16
17
  end
17
18
 
18
19
  def action_logger
@@ -34,8 +34,8 @@ module Dynflow
34
34
  @director.work_finished(work_item)
35
35
  end
36
36
 
37
- def event(execution_plan_id, step_id, event, future = Concurrent::Promises.resolvable_future)
38
- event = (Director::Event[SecureRandom.uuid, execution_plan_id, step_id, event, future])
37
+ def event(execution_plan_id, step_id, event, future = Concurrent::Promises.resolvable_future, optional: false)
38
+ event = (Director::Event[SecureRandom.uuid, execution_plan_id, step_id, event, future, optional])
39
39
  @director.handle_event(event).each do |work_item|
40
40
  @work_items << work_item
41
41
  end
@@ -58,15 +58,15 @@ module Dynflow
58
58
  future.reject e
59
59
  end
60
60
 
61
- def event(execution_plan_id, step_id, event, done = Concurrent::Promises.resolvable_future)
62
- @executor.event(execution_plan_id, step_id, event, done)
61
+ def event(execution_plan_id, step_id, event, done = Concurrent::Promises.resolvable_future, optional: false)
62
+ @executor.event(execution_plan_id, step_id, event, done, optional: optional)
63
63
  end
64
64
 
65
- def plan_event(execution_plan_id, step_id, event, time, done = Concurrent::Promises.resolvable_future)
65
+ def plan_event(execution_plan_id, step_id, event, time, done = Concurrent::Promises.resolvable_future, optional: false)
66
66
  if time.nil? || time < Time.now
67
- event(execution_plan_id, step_id, event, done)
67
+ event(execution_plan_id, step_id, event, done, optional: optional)
68
68
  else
69
- clock.ping(executor, time, Director::Event[SecureRandom.uuid, execution_plan_id, step_id, event, done], :delayed_event)
69
+ clock.ping(executor, time, Director::Event[SecureRandom.uuid, execution_plan_id, step_id, event, done, optional], :delayed_event)
70
70
  end
71
71
  end
72
72
  end
@@ -19,6 +19,7 @@ module Dynflow
19
19
 
20
20
  require 'dynflow/testing/mimic'
21
21
  require 'dynflow/testing/managed_clock'
22
+ require 'dynflow/testing/dummy_coordinator'
22
23
  require 'dynflow/testing/dummy_world'
23
24
  require 'dynflow/testing/dummy_executor'
24
25
  require 'dynflow/testing/dummy_execution_plan'
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Dynflow
3
- VERSION = '1.4.7'
3
+ VERSION = '1.6.1'
4
4
  end
data/lib/dynflow/world.rb CHANGED
@@ -200,6 +200,14 @@ module Dynflow
200
200
  Scheduled[execution_plan.id]
201
201
  end
202
202
 
203
+ def plan_elsewhere(action_class, *args)
204
+ execution_plan = ExecutionPlan.new(self, nil)
205
+ execution_plan.delay(nil, action_class, {}, *args)
206
+ plan_request(execution_plan.id)
207
+
208
+ Scheduled[execution_plan.id]
209
+ end
210
+
203
211
  def plan(action_class, *args)
204
212
  plan_with_options(action_class: action_class, args: args)
205
213
  end
@@ -219,12 +227,16 @@ module Dynflow
219
227
  publish_request(Dispatcher::Execution[execution_plan_id], done, true)
220
228
  end
221
229
 
222
- def event(execution_plan_id, step_id, event, done = Concurrent::Promises.resolvable_future)
223
- publish_request(Dispatcher::Event[execution_plan_id, step_id, event], done, false)
230
+ def event(execution_plan_id, step_id, event, done = Concurrent::Promises.resolvable_future, optional: false)
231
+ publish_request(Dispatcher::Event[execution_plan_id, step_id, event, nil, optional], done, false)
232
+ end
233
+
234
+ def plan_event(execution_plan_id, step_id, event, time, accepted = Concurrent::Promises.resolvable_future, optional: false)
235
+ publish_request(Dispatcher::Event[execution_plan_id, step_id, event, time, optional], accepted, false)
224
236
  end
225
237
 
226
- def plan_event(execution_plan_id, step_id, event, time, accepted = Concurrent::Promises.resolvable_future)
227
- publish_request(Dispatcher::Event[execution_plan_id, step_id, event, time], accepted, false)
238
+ def plan_request(execution_plan_id, done = Concurrent::Promises.resolvable_future)
239
+ publish_request(Dispatcher::Planning[execution_plan_id], done, false)
228
240
  end
229
241
 
230
242
  def ping(world_id, timeout, done = Concurrent::Promises.resolvable_future)
data/lib/dynflow.rb CHANGED
@@ -72,11 +72,12 @@ module Dynflow
72
72
  require 'dynflow/throttle_limiter'
73
73
  require 'dynflow/telemetry'
74
74
  require 'dynflow/config'
75
+ require 'dynflow/extensions'
75
76
 
76
77
  if defined? ::ActiveJob
77
78
  require 'dynflow/active_job/queue_adapter'
78
79
 
79
- class Railtie < Rails::Railtie
80
+ class Railtie < ::Rails::Railtie
80
81
  config.before_initialize do
81
82
  ::ActiveJob::QueueAdapters.send(
82
83
  :include,
@@ -49,6 +49,12 @@ module Dynflow
49
49
  plan = result.finished.value
50
50
  assert_equal('finish', plan.actions.first.output[:event])
51
51
  end
52
+
53
+ it 'does not error on dispatching an optional event' do
54
+ request = client_world.event('123', 1, nil, optional: true)
55
+ request.wait(20)
56
+ assert_match /Could not find an executor for optional .*, discarding/, request.reason.message
57
+ end
52
58
  end
53
59
  end
54
60
  end
@@ -60,6 +60,18 @@ module Dynflow
60
60
  execution_plan_hooks.use :raise_flag_root_only, :on => :stopped
61
61
  end
62
62
 
63
+ class PendingAction < ::Dynflow::Action
64
+ include FlagHook
65
+
66
+ execution_plan_hooks.use :raise_flag, :on => :pending
67
+ end
68
+
69
+ class AllTransitionsAction < ::Dynflow::Action
70
+ include FlagHook
71
+
72
+ execution_plan_hooks.use :raise_flag
73
+ end
74
+
63
75
  class ComposedAction < RootOnlyAction
64
76
  def plan
65
77
  plan_action(RootOnlyAction)
@@ -161,6 +173,30 @@ module Dynflow
161
173
  plan.finished.wait!
162
174
  _(Flag.raised_count).must_equal 1
163
175
  end
176
+
177
+ it 'runs the pending hooks when execution plan is created' do
178
+ refute Flag.raised?
179
+ plan = world.trigger(PendingAction)
180
+ plan.finished.wait!
181
+ _(Flag.raised_count).must_equal 1
182
+ end
183
+
184
+ it 'runs the pending hooks when execution plan is created' do
185
+ refute Flag.raised?
186
+ delay = world.delay(PendingAction, { :start_at => Time.now.utc + 180 })
187
+ delayed_plan = world.persistence.load_delayed_plan(delay.execution_plan_id)
188
+ delayed_plan.execution_plan.cancel.each(&:wait)
189
+ _(Flag.raised_count).must_equal 1
190
+ end
191
+
192
+ it 'runs the hook on every state transition' do
193
+ refute Flag.raised?
194
+ plan = world.trigger(AllTransitionsAction)
195
+ plan.finished.wait!
196
+ # There should be 5 transitions
197
+ # nothing -> pending -> planning -> planned -> running -> stopped
198
+ _(Flag.raised_count).must_equal 5
199
+ end
164
200
  end
165
201
  end
166
202
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'test_helper'
3
+ require 'active_support/time'
4
+
5
+ module Dynflow
6
+ module ExtensionsTest
7
+ describe 'msgpack extensions' do
8
+ before do
9
+ Thread.current[:time_zone] = ActiveSupport::TimeZone['Europe/Prague']
10
+ end
11
+ after { Thread.current[:time_zone] = nil }
12
+
13
+ it 'allows {de,}serializing Time' do
14
+ time = Time.now
15
+ transformed = MessagePack.unpack(time.to_msgpack)
16
+ assert_equal transformed, time
17
+ assert_equal transformed.class, time.class
18
+ end
19
+
20
+ it 'allows {de,}serializing ActiveSupport::TimeWithZone' do
21
+ time = Time.zone.now
22
+ transformed = MessagePack.unpack(time.to_msgpack)
23
+ assert_equal transformed, time
24
+ assert_equal transformed.class, time.class
25
+ end
26
+
27
+ it 'allows {de,}serializing DateTime' do
28
+ time = DateTime.now
29
+ transformed = MessagePack.unpack(time.to_msgpack)
30
+ assert_equal transformed, time
31
+ assert_equal transformed.class, time.class
32
+ end
33
+
34
+ it 'allows {de,}serializing Date' do
35
+ date = DateTime.current
36
+ transformed = MessagePack.unpack(date.to_msgpack)
37
+ assert_equal transformed, date
38
+ assert_equal transformed.class, date.class
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'test_helper'
3
+ require 'mocha/minitest'
4
+
5
+ module Dynflow
6
+ describe 'flow' do
7
+
8
+ class TestRegistry < Flows::Registry
9
+ class << self
10
+ def reset!
11
+ @serialization_map = {}
12
+ end
13
+ end
14
+ end
15
+
16
+ after do
17
+ TestRegistry.reset!
18
+ end
19
+
20
+ describe "registry" do
21
+ it "allows registering values" do
22
+ TestRegistry.register!(TestRegistry, 'TS')
23
+ TestRegistry.register!(Integer, 'I')
24
+ map = TestRegistry.instance_variable_get("@serialization_map")
25
+ _(map).must_equal({'TS' => TestRegistry, 'I' => Integer})
26
+ end
27
+
28
+ it "prevents overwriting values" do
29
+ TestRegistry.register!(Integer, 'I')
30
+ _(-> { TestRegistry.register!(Float, 'I') }).must_raise Flows::Registry::IdentifierTaken
31
+ end
32
+
33
+ it "encodes and decodes values" do
34
+ TestRegistry.register!(Integer, 'I')
35
+ _(TestRegistry.encode(Integer)).must_equal 'I'
36
+ end
37
+
38
+ it "raises an exception when unknown key is requested" do
39
+ _(-> { TestRegistry.encode(Float) }).must_raise Flows::Registry::UnknownIdentifier
40
+ _(-> { TestRegistry.decode('F') }).must_raise Flows::Registry::UnknownIdentifier
41
+ end
42
+ end
43
+ end
44
+ end
@@ -29,14 +29,17 @@ module Dynflow
29
29
  describe 'abstract executor' do
30
30
  let(:abstract_delayed_executor) { DelayedExecutors::AbstractCore.new(world) }
31
31
 
32
- it 'handles wrong plan state' do
32
+ it 'handles plan in planning state' do
33
33
  delayed_plan.execution_plan.state = :planning
34
34
  abstract_delayed_executor.send(:process, [delayed_plan], @start_at)
35
- _(delayed_plan.execution_plan.state).must_equal :planned
35
+ _(delayed_plan.execution_plan.state).must_equal :scheduled
36
+ end
36
37
 
38
+ it 'handles plan in running state' do
37
39
  delayed_plan.execution_plan.set_state(:running, true)
38
40
  abstract_delayed_executor.send(:process, [delayed_plan], @start_at)
39
41
  _(delayed_plan.execution_plan.state).must_equal :running
42
+ _(world.persistence.load_delayed_plan(delayed_plan.execution_plan_uuid)).must_be :nil?
40
43
  end
41
44
  end
42
45
 
@@ -55,7 +58,7 @@ module Dynflow
55
58
 
56
59
  it 'delays the action' do
57
60
  _(execution_plan.steps.count).must_equal 1
58
- _(delayed_plan.start_at.inspect).must_equal (@start_at).inspect
61
+ _(delayed_plan.start_at.to_i).must_equal(@start_at.to_i)
59
62
  _(history_names.call(execution_plan)).must_equal ['delay']
60
63
  end
61
64
 
@@ -86,7 +86,7 @@ module Dynflow
86
86
  original.each do |key, value|
87
87
  loaded_value = loaded[key.to_s]
88
88
  if value.is_a?(Time)
89
- _(loaded_value.inspect).must_equal value.inspect
89
+ _(loaded_value).must_be_within_delta(value, 0.5)
90
90
  elsif value.is_a?(Hash)
91
91
  assert_equal_attributes!(value, loaded_value)
92
92
  elsif value.nil?
@@ -348,7 +348,7 @@ module Dynflow
348
348
  if value.nil?
349
349
  assert_nil stored.fetch(name.to_sym)
350
350
  elsif value.is_a?(Time)
351
- _(stored.fetch(name.to_sym).inspect).must_equal value.inspect
351
+ _(stored.fetch(name.to_sym)).must_be_within_delta(value, 0.5)
352
352
  else
353
353
  _(stored.fetch(name.to_sym)).must_equal value
354
354
  end
@@ -31,6 +31,7 @@
31
31
  <% end %>
32
32
  <%= show_action_data("Input:", action.input) %>
33
33
  <%= show_action_data("Output:", action.output) %>
34
+ <%= show_action_data("Chunked output:", action.stored_output_chunks) %>
34
35
  <% if step.error %>
35
36
  <p>
36
37
  <b>Error:</b>
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.7
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Necas
8
8
  - Petr Chalupa
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 1970-01-01 00:00:00.000000000 Z
12
+ date: 2021-09-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: msgpack
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 1.3.3
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 1.3.3
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: apipie-params
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -242,10 +256,11 @@ executables: []
242
256
  extensions: []
243
257
  extra_rdoc_files: []
244
258
  files:
259
+ - ".github/install_dependencies.sh"
260
+ - ".github/workflows/ruby.yml"
245
261
  - ".gitignore"
246
262
  - ".rubocop.yml"
247
263
  - ".rubocop_todo.yml"
248
- - ".travis.yml"
249
264
  - Dockerfile
250
265
  - Gemfile
251
266
  - MIT-LICENSE
@@ -386,6 +401,7 @@ files:
386
401
  - doc/pages/source/projects/index.md
387
402
  - docker-compose.yml
388
403
  - dynflow.gemspec
404
+ - examples/chunked_output_benchmark.rb
389
405
  - examples/clock_benchmark.rb
390
406
  - examples/example_helper.rb
391
407
  - examples/future_execution.rb
@@ -397,6 +413,7 @@ files:
397
413
  - examples/sub_plan_concurrency_control.rb
398
414
  - examples/sub_plans.rb
399
415
  - examples/termination.rb
416
+ - extras/expand/main.go
400
417
  - extras/statsd_mapping.conf
401
418
  - lib/dynflow.rb
402
419
  - lib/dynflow/action.rb
@@ -469,11 +486,14 @@ files:
469
486
  - lib/dynflow/executors/sidekiq/redis_locking.rb
470
487
  - lib/dynflow/executors/sidekiq/serialization.rb
471
488
  - lib/dynflow/executors/sidekiq/worker_jobs.rb
489
+ - lib/dynflow/extensions.rb
490
+ - lib/dynflow/extensions/msgpack.rb
472
491
  - lib/dynflow/flows.rb
473
492
  - lib/dynflow/flows/abstract.rb
474
493
  - lib/dynflow/flows/abstract_composed.rb
475
494
  - lib/dynflow/flows/atom.rb
476
495
  - lib/dynflow/flows/concurrence.rb
496
+ - lib/dynflow/flows/registry.rb
477
497
  - lib/dynflow/flows/sequence.rb
478
498
  - lib/dynflow/logger_adapters.rb
479
499
  - lib/dynflow/logger_adapters/abstract.rb
@@ -513,6 +533,9 @@ files:
513
533
  - lib/dynflow/persistence_adapters/sequel_migrations/018_add_uuid_column.rb
514
534
  - lib/dynflow/persistence_adapters/sequel_migrations/019_update_mysql_time_precision.rb
515
535
  - lib/dynflow/persistence_adapters/sequel_migrations/020_drop_duplicate_indices.rb
536
+ - lib/dynflow/persistence_adapters/sequel_migrations/021_create_output_chunks.rb
537
+ - lib/dynflow/persistence_adapters/sequel_migrations/022_store_flows_as_msgpack.rb
538
+ - lib/dynflow/persistence_adapters/sequel_migrations/023_sqlite_workarounds.rb
516
539
  - lib/dynflow/rails.rb
517
540
  - lib/dynflow/rails/configuration.rb
518
541
  - lib/dynflow/rails/daemon.rb
@@ -534,6 +557,7 @@ files:
534
557
  - lib/dynflow/telemetry_adapters/statsd.rb
535
558
  - lib/dynflow/testing.rb
536
559
  - lib/dynflow/testing/assertions.rb
560
+ - lib/dynflow/testing/dummy_coordinator.rb
537
561
  - lib/dynflow/testing/dummy_execution_plan.rb
538
562
  - lib/dynflow/testing/dummy_executor.rb
539
563
  - lib/dynflow/testing/dummy_planned_action.rb
@@ -576,11 +600,12 @@ files:
576
600
  - test/execution_plan_hooks_test.rb
577
601
  - test/execution_plan_test.rb
578
602
  - test/executor_test.rb
603
+ - test/extensions_test.rb
604
+ - test/flows_test.rb
579
605
  - test/future_execution_test.rb
580
606
  - test/memory_cosumption_watcher_test.rb
581
607
  - test/middleware_test.rb
582
608
  - test/persistence_test.rb
583
- - test/prepare_travis_env.sh
584
609
  - test/redis_locking_test.rb
585
610
  - test/rescue_test.rb
586
611
  - test/round_robin_test.rb
@@ -625,7 +650,7 @@ homepage: https://github.com/Dynflow/dynflow
625
650
  licenses:
626
651
  - MIT
627
652
  metadata: {}
628
- post_install_message:
653
+ post_install_message:
629
654
  rdoc_options: []
630
655
  require_paths:
631
656
  - lib
@@ -641,7 +666,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
641
666
  version: '0'
642
667
  requirements: []
643
668
  rubygems_version: 3.1.2
644
- signing_key:
669
+ signing_key:
645
670
  specification_version: 4
646
671
  summary: DYNamic workFLOW engine
647
672
  test_files:
@@ -659,11 +684,12 @@ test_files:
659
684
  - test/execution_plan_hooks_test.rb
660
685
  - test/execution_plan_test.rb
661
686
  - test/executor_test.rb
687
+ - test/extensions_test.rb
688
+ - test/flows_test.rb
662
689
  - test/future_execution_test.rb
663
690
  - test/memory_cosumption_watcher_test.rb
664
691
  - test/middleware_test.rb
665
692
  - test/persistence_test.rb
666
- - test/prepare_travis_env.sh
667
693
  - test/redis_locking_test.rb
668
694
  - test/rescue_test.rb
669
695
  - test/round_robin_test.rb