dynflow 1.6.11 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db2725603e440298025d434778ebf2e218e6c3e30fb7db07aaddea80648cbb2d
4
- data.tar.gz: 4d8003de94bec301bd411c1c3ee92df9e1d10cc45bc36d4d843a75c2eb664171
3
+ metadata.gz: b1fd4cb9db86befb0bfc96cd5c98f2ca9aa0f6f40249712cbbb8b250b9b9a142
4
+ data.tar.gz: 218d8a4ce5ec717f24ca4d5d730a5c0620f65ab00e6a35e0595a18876f4b9a31
5
5
  SHA512:
6
- metadata.gz: ab0fa706aa8b41c1197aef44bf57a87f4e5c37d7d343a9ca7e83e20af8de89b4e0fb2e72e7a1b93fffa05ac3265c78a48d598d7b8e0292785cd2276057edd0f0
7
- data.tar.gz: 07e82b78806a61511b0ddff0240dd596172dfe79735bc8b931d7972b4d322d29bca1686be8be0087a105171e7348c0ee24cfdb2b01cc1a8dcf8d97ad8b0134c8
6
+ metadata.gz: 80b8644418108a107c2a73481fb793647ac6ce40f9789b4efa064970bd6cccd54579ce95ff0b5a4710f033e4defaa7d0fd50ec96d9c51e91666adcd875cc9cc4
7
+ data.tar.gz: 6a28661cdfeff6555c970df957f10f28d4c23baf977b1212cf3253bac973cef967b1c40be7b77dbaa3fe6811e484be319a04417a0895dd81a32edd534ce58975
@@ -35,10 +35,9 @@ jobs:
35
35
  fail-fast: false
36
36
  matrix:
37
37
  ruby_version:
38
- - 2.5.0
39
- - 2.6.0
40
38
  - 2.7.0
41
39
  - 3.0.0
40
+ - 3.2.0
42
41
  concurrent_ruby_ext:
43
42
  - 'true'
44
43
  - 'false'
@@ -54,30 +53,23 @@ jobs:
54
53
  - db: sqlite3
55
54
  conn_string: sqlite:/
56
55
  exclude:
57
- - db: mysql
58
- ruby_version: 2.5.0
59
- - db: mysql
60
- ruby_version: 2.6.0
61
56
  - db: mysql
62
57
  ruby_version: 3.0.0
58
+ - db: mysql
59
+ ruby_version: 3.2.0
63
60
  - db: mysql
64
61
  concurrent_ruby_ext: 'true'
65
- - db: sqlite3
66
- ruby_version: 2.5.0
67
- - db: sqlite3
68
- ruby_version: 2.6.0
69
62
  - db: sqlite3
70
63
  ruby_version: 3.0.0
64
+ - db: sqlite3
65
+ ruby_version: 3.2.0
71
66
  - db: sqlite3
72
67
  concurrent_ruby_ext: 'true'
73
68
  - db: postgresql
74
- ruby_version: 2.5.0
75
- concurrent_ruby_ext: 'true'
76
- - db: postgresql
77
- ruby_version: 2.6.0
69
+ ruby_version: 3.0.0
78
70
  concurrent_ruby_ext: 'true'
79
71
  - db: postgresql
80
- ruby_version: 3.0.0
72
+ ruby_version: 3.2.0
81
73
  concurrent_ruby_ext: 'true'
82
74
 
83
75
  services:
@@ -179,6 +179,12 @@ module Dynflow
179
179
  @output_chunks ||= world.persistence.load_output_chunks(@execution_plan_id, @id)
180
180
  end
181
181
 
182
+ def drop_output_chunks!
183
+ @pending_output_chunks = []
184
+ @output_chunks = []
185
+ world.persistence.delete_output_chunks(@execution_plan_id, @id)
186
+ end
187
+
182
188
  def caller_action
183
189
  phase! Present
184
190
  return nil if @caller_action_id
@@ -56,12 +56,20 @@ module Dynflow
56
56
  adapter.load_output_chunks(execution_plan_id, action_id)
57
57
  end
58
58
 
59
+ def delete_output_chunks(execution_plan_id, action_id)
60
+ adapter.delete_output_chunks(execution_plan_id, action_id)
61
+ end
62
+
59
63
  def find_execution_plans(options)
60
64
  adapter.find_execution_plans(options).map do |execution_plan_hash|
61
65
  ExecutionPlan.new_from_hash(execution_plan_hash, @world)
62
66
  end
63
67
  end
64
68
 
69
+ def find_execution_plan_statuses(options)
70
+ adapter.find_execution_plan_statuses(options)
71
+ end
72
+
65
73
  def find_execution_plan_counts(options)
66
74
  adapter.find_execution_plan_counts(options)
67
75
  end
@@ -46,6 +46,10 @@ module Dynflow
46
46
  filter(:execution_plan, options[:filters]).count
47
47
  end
48
48
 
49
+ def find_execution_plan_statuses(options)
50
+ raise NotImplementedError
51
+ end
52
+
49
53
  # @param filters [Hash{ String => Object }] filters to determine
50
54
  # what to delete
51
55
  # @param batch_size the size of the chunks to iterate over when
@@ -104,6 +108,18 @@ module Dynflow
104
108
  raise NotImplementedError
105
109
  end
106
110
 
111
+ def save_output_chunks(execution_plan_id, action_id, chunks)
112
+ raise NotImplementedError
113
+ end
114
+
115
+ def load_output_chunks(execution_plan_id, action_id)
116
+ raise NotImplementedError
117
+ end
118
+
119
+ def delete_output_chunks(execution_plan_id, action_id)
120
+ raise NotImplementedError
121
+ end
122
+
107
123
  # for debug purposes
108
124
  def to_hash
109
125
  raise NotImplementedError
@@ -78,6 +78,16 @@ module Dynflow
78
78
  filter(:execution_plan, table(:execution_plan), options[:filters]).count
79
79
  end
80
80
 
81
+ def find_execution_plan_statuses(options)
82
+ plans = filter(:execution_plan, table(:execution_plan), options[:filters])
83
+ .select(:uuid, :state, :result)
84
+
85
+ plans.each_with_object({}) do |current, acc|
86
+ uuid = current.delete(:uuid)
87
+ acc[uuid] = current
88
+ end
89
+ end
90
+
81
91
  def delete_execution_plans(filters, batch_size = 1000, backup_dir = nil)
82
92
  count = 0
83
93
  filter(:execution_plan, table(:execution_plan), filters).each_slice(batch_size) do |plans|
@@ -190,6 +200,10 @@ module Dynflow
190
200
  load_records :output_chunk, { execution_plan_uuid: execution_plan_id, action_id: action_id }, [:timestamp, :kind, :chunk]
191
201
  end
192
202
 
203
+ def delete_output_chunks(execution_plan_id, action_id)
204
+ filter(:output_chunk, table(:output_chunk), { execution_plan_uuid: execution_plan_id, action_id: action_id }).delete
205
+ end
206
+
193
207
  def connector_feature!
194
208
  unless @additional_responsibilities[:connector]
195
209
  raise "The sequel persistence adapter connector feature used but not enabled in additional_features"
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Dynflow
3
- VERSION = '1.6.11'
3
+ VERSION = '1.7.0'
4
4
  end
data/test/action_test.rb CHANGED
@@ -889,5 +889,48 @@ module Dynflow
889
889
  end
890
890
  end
891
891
  end
892
+
893
+ describe 'output chunks' do
894
+ include ::Dynflow::Testing::Factories
895
+
896
+ class OutputChunkAction < ::Dynflow::Action
897
+ def run(event = nil)
898
+ output[:counter] ||= 0
899
+ case event
900
+ when nil
901
+ output_chunk("Chunk #{output[:counter]}")
902
+ output[:counter] += 1
903
+ suspend
904
+ when :exit
905
+ return
906
+ end
907
+ end
908
+
909
+ def finalize
910
+ drop_output_chunks!
911
+ end
912
+ end
913
+
914
+ it 'collects and drops output chunks' do
915
+ action = create_and_plan_action(OutputChunkAction)
916
+ _(action.pending_output_chunks).must_equal nil
917
+
918
+ action = run_action(action)
919
+ _(action.pending_output_chunks.count).must_equal 1
920
+
921
+ action = run_action(action)
922
+ _(action.pending_output_chunks.count).must_equal 2
923
+
924
+ action = run_action(action, :exit)
925
+ _(action.pending_output_chunks.count).must_equal 2
926
+
927
+ persistence = mock()
928
+ persistence.expects(:delete_output_chunks).with(action.execution_plan_id, action.id)
929
+ action.world.stubs(:persistence).returns(persistence)
930
+
931
+ action = finalize_action(action)
932
+ _(action.pending_output_chunks.count).must_equal 0
933
+ end
934
+ end
892
935
  end
893
936
  end
@@ -159,6 +159,46 @@ module Dynflow
159
159
  end
160
160
  end
161
161
 
162
+ describe '#def find_execution_plan_statuses' do
163
+ before do
164
+ # the tests expect clean field
165
+ adapter.delete_execution_plans({})
166
+ end
167
+
168
+ it 'supports filtering' do
169
+ prepare_and_save_plans
170
+ if adapter.ordering_by.include?('state')
171
+ loaded_plans = adapter.find_execution_plan_statuses(filters: { label: ['test1'] })
172
+ _(loaded_plans).must_equal({ 'plan1' => { state: 'paused', result: nil} })
173
+
174
+ loaded_plans = adapter.find_execution_plan_statuses(filters: { state: ['paused'] })
175
+ _(loaded_plans).must_equal({"plan1"=>{:state=>"paused", :result=>nil},
176
+ "plan3"=>{:state=>"paused", :result=>nil},
177
+ "plan4"=>{:state=>"paused", :result=>nil}})
178
+
179
+ loaded_plans = adapter.find_execution_plan_statuses(filters: { state: ['stopped'] })
180
+ _(loaded_plans).must_equal({"plan2"=>{:state=>"stopped", :result=>nil}})
181
+
182
+ loaded_plans = adapter.find_execution_plan_statuses(filters: { state: [] })
183
+ _(loaded_plans).must_equal({})
184
+
185
+ loaded_plans = adapter.find_execution_plan_statuses(filters: { state: ['stopped', 'paused'] })
186
+ _(loaded_plans).must_equal({"plan1"=>{:state=>"paused", :result=>nil},
187
+ "plan2"=>{:state=>"stopped", :result=>nil},
188
+ "plan3"=>{:state=>"paused", :result=>nil}, "plan4"=>{:state=>"paused", :result=>nil}})
189
+
190
+ loaded_plans = adapter.find_execution_plan_statuses(filters: { 'state' => ['stopped', 'paused'] })
191
+ _(loaded_plans).must_equal({"plan1"=>{:state=>"paused", :result=>nil},
192
+ "plan2"=>{:state=>"stopped", :result=>nil},
193
+ "plan3"=>{:state=>"paused", :result=>nil},
194
+ "plan4"=>{:state=>"paused", :result=>nil}})
195
+
196
+ loaded_plans = adapter.find_execution_plan_statuses(filters: { label: ['test1'], :delayed => true })
197
+ _(loaded_plans).must_equal({})
198
+ end
199
+ end
200
+ end
201
+
162
202
  describe '#def find_execution_plan_counts' do
163
203
  before do
164
204
  # the tests expect clean field
@@ -331,6 +371,20 @@ module Dynflow
331
371
  _(plans.first[:execution_plan_uuid]).must_equal 'plan1'
332
372
  end
333
373
  end
374
+
375
+ describe '#delete_output_chunks' do
376
+ it 'deletes output chunks' do
377
+ prepare_plans_with_actions
378
+
379
+ adapter.save_output_chunks('plan1', 1, [{chunk: "Hello", timestamp: Time.now}, {chunk: "Bye", timestamp: Time.now}])
380
+ chunks = adapter.load_output_chunks('plan1', 1)
381
+ _(chunks.length).must_equal 2
382
+ deleted = adapter.delete_output_chunks('plan1', 1)
383
+ _(deleted).must_equal 2
384
+ chunks = adapter.load_output_chunks('plan1', 1)
385
+ _(chunks.length).must_equal 0
386
+ end
387
+ end
334
388
  end
335
389
 
336
390
  describe Dynflow::PersistenceAdapters::Sequel do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.11
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Necas
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-05-09 00:00:00.000000000 Z
12
+ date: 2023-05-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json