dynflow 1.4.7 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
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