taskflow 5.9.0__py3-none-any.whl → 5.9.1__py3-none-any.whl

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.
@@ -291,6 +291,18 @@ class Runtime(object):
291
291
  """Resets all the provided atoms to the given state and intention."""
292
292
  tweaked = []
293
293
  for atom in atoms:
294
+ cur_intention = self.storage.get_atom_intention(atom.name)
295
+ # Don't trigger a RETRY if the atom needs to be REVERTED.
296
+ # This is a workaround for a bug when REVERT_ALL is applied to
297
+ # unordered flows
298
+ # (https://bugs.launchpad.net/taskflow/+bug/2043808)
299
+ # A subflow may trigger a REVERT_ALL, all the atoms of all the
300
+ # related subflows are marked as REVERT but a task of a related
301
+ # flow may still be running in another thread. If this task
302
+ # triggers a RETRY, it overrides the previously set REVERT status,
303
+ # breaking the revert path of the flow.
304
+ if cur_intention == st.REVERT and intention == st.RETRY:
305
+ continue
294
306
  if state or intention:
295
307
  tweaked.append((atom, state, intention))
296
308
  if state:
@@ -15,8 +15,10 @@
15
15
  # under the License.
16
16
 
17
17
  import testtools
18
+ import time
18
19
 
19
20
  import taskflow.engines
21
+ from taskflow.engines.action_engine import executor
20
22
  from taskflow import exceptions as exc
21
23
  from taskflow.patterns import graph_flow as gf
22
24
  from taskflow.patterns import linear_flow as lf
@@ -502,6 +504,56 @@ class RetryTest(utils.EngineTestBase):
502
504
  self.assertRaisesRegex(RuntimeError, '^Woot', engine.run)
503
505
  self.assertRaisesRegex(RuntimeError, '^Woot', engine.run)
504
506
 
507
+ def test_restart_reverted_unordered_flows_with_retries(self):
508
+ now = time.time()
509
+
510
+ # First flow of an unordered flow:
511
+ subflow1 = lf.Flow('subflow1')
512
+
513
+ # * a task that completes in 3 sec with a few retries
514
+ subsubflow1 = lf.Flow('subflow1.subsubflow1',
515
+ retry=utils.RetryFiveTimes())
516
+ subsubflow1.add(utils.SuccessAfter3Sec('subflow1.fail1',
517
+ inject={'start_time': now}))
518
+ subflow1.add(subsubflow1)
519
+
520
+ # * a task that fails and triggers a revert after 5 retries
521
+ subsubflow2 = lf.Flow('subflow1.subsubflow2',
522
+ retry=utils.RetryFiveTimes())
523
+ subsubflow2.add(utils.FailingTask('subflow1.fail2'))
524
+ subflow1.add(subsubflow2)
525
+
526
+ # Second flow of the unordered flow:
527
+ subflow2 = lf.Flow('subflow2')
528
+
529
+ # * a task that always fails and retries
530
+ subsubflow1 = lf.Flow('subflow2.subsubflow1',
531
+ retry=utils.AlwaysRetry())
532
+ subsubflow1.add(utils.FailingTask('subflow2.fail1'))
533
+ subflow2.add(subsubflow1)
534
+
535
+ unordered_flow = uf.Flow('unordered_flow')
536
+ unordered_flow.add(subflow1, subflow2)
537
+
538
+ # Main flow, contains a simple task and an unordered flow
539
+ flow = lf.Flow('test')
540
+ flow.add(utils.NoopTask('task1'))
541
+ flow.add(unordered_flow)
542
+
543
+ engine = self._make_engine(flow)
544
+
545
+ # This test fails when using Green threads, skipping it for now
546
+ if isinstance(engine._task_executor,
547
+ executor.ParallelGreenThreadTaskExecutor):
548
+ self.skipTest("Skipping this test when using green threads.")
549
+
550
+ with utils.CaptureListener(engine) as capturer:
551
+ self.assertRaisesRegex(exc.WrappedFailure,
552
+ '.*RuntimeError: Woot!',
553
+ engine.run)
554
+ # task1 should have been reverted
555
+ self.assertIn('task1.t REVERTED(None)', capturer.values)
556
+
505
557
  def test_run_just_retry(self):
506
558
  flow = utils.OneReturnRetry(provides='x')
507
559
  engine = self._make_engine(flow)
taskflow/tests/utils.py CHANGED
@@ -227,6 +227,32 @@ class FailingTask(ProgressingTask):
227
227
  raise RuntimeError('Woot!')
228
228
 
229
229
 
230
+ class SimpleTask(task.Task):
231
+ def execute(self, time_sleep=0, **kwargs):
232
+ time.sleep(time_sleep)
233
+
234
+
235
+ class SuccessAfter3Sec(task.Task):
236
+ def execute(self, start_time, **kwargs):
237
+ now = time.time()
238
+ if now - start_time >= 3:
239
+ return None
240
+ raise RuntimeError('Woot!')
241
+
242
+
243
+ class RetryFiveTimes(retry.Times):
244
+ def on_failure(self, history, *args, **kwargs):
245
+ if len(history) < 5:
246
+ time.sleep(1)
247
+ return retry.RETRY
248
+ return retry.REVERT_ALL
249
+
250
+
251
+ class AlwaysRetry(retry.Times):
252
+ def on_failure(self, history, *args, **kwargs):
253
+ return retry.RETRY
254
+
255
+
230
256
  class OptionalTask(task.Task):
231
257
  def execute(self, a, b=5):
232
258
  result = a * b
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: taskflow
3
- Version: 5.9.0
3
+ Version: 5.9.1
4
4
  Summary: Taskflow structured state management library.
5
5
  Home-page: https://docs.openstack.org/taskflow/latest/
6
6
  Author: OpenStack
@@ -29,7 +29,7 @@ taskflow/engines/action_engine/deciders.py,sha256=WEKo189CL9Zdg506Sz3Mlxpfp6dqGv
29
29
  taskflow/engines/action_engine/engine.py,sha256=kz_9BVD22IO2mEHBc735zUDPCF0Y_hzcAuQqZpUUVCk,29817
30
30
  taskflow/engines/action_engine/executor.py,sha256=sBmKwgDQN9fEZz42T7RB-RYUZvWqfHqC-Y2EsWRGkYI,7749
31
31
  taskflow/engines/action_engine/process_executor.py,sha256=if8kc7Dg3lvT7NwKVe2eqHhksv1pxEPNoI5E80naGr4,27975
32
- taskflow/engines/action_engine/runtime.py,sha256=exGFpk7iPPrl7vywAHqdeDW-cyFlYxphPLi8W1umP3o,13845
32
+ taskflow/engines/action_engine/runtime.py,sha256=FAUJZsZaADo4t1kRzs0Pf5z2qRjrlNG5GCycUoe4N8U,14604
33
33
  taskflow/engines/action_engine/scheduler.py,sha256=yZEn2z23N-0XNpHtjOs3kxJh4CTpZl-2ASrPsyLP2t0,4048
34
34
  taskflow/engines/action_engine/scopes.py,sha256=u0cmoMycrNZqMebgKqLW2YXBVLukNi9dVqKOFr79lKw,5432
35
35
  taskflow/engines/action_engine/selector.py,sha256=9FKRKOi6mqIn4kfEY2R6Uq6aVzPPsT0DgI1VDVRaZdU,11558
@@ -149,7 +149,7 @@ taskflow/persistence/backends/sqlalchemy/alembic/versions/README,sha256=AwegmiWc
149
149
  taskflow/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
150
  taskflow/tests/fixtures.py,sha256=VfGlusX2q79_ktPME4cm1qt_gN9VNRAwyYy5sDBAX0Y,2004
151
151
  taskflow/tests/test_examples.py,sha256=g2zhguLKE4Tex2e_vSmKMhsNXItnKWj89_VbnmgGejU,4925
152
- taskflow/tests/utils.py,sha256=rT29L0V0rIB1SopQgSXRDMNYBfm1msrHowH1FH9D_V8,11323
152
+ taskflow/tests/utils.py,sha256=go8D7cUHQJ31F0n0Ts5ijeHdC7JsCFpsgdHb09QL5A4,11954
153
153
  taskflow/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
154
  taskflow/tests/unit/test_arguments_passing.py,sha256=jK9-Z7xBfPI4nHB7_Bh_rllBH-X55v6wplxdrjwRS3E,9381
155
155
  taskflow/tests/unit/test_check_transition.py,sha256=DuxJAErCwheWPAdN_43LOOvZg00vmUoC-IzGgh642IM,6173
@@ -167,7 +167,7 @@ taskflow/tests/unit/test_mapfunctor_task.py,sha256=1FI8AJxRUPxT7Lu6h9Mhd62srAnKf
167
167
  taskflow/tests/unit/test_notifier.py,sha256=Q4xGl9e_LZRiJVpGR2FbG2qSp9CqlP65aDsaIKxPqHI,7894
168
168
  taskflow/tests/unit/test_progress.py,sha256=oeYFeWuHde1D2cAahhE1yN1NznNcXk7ajw0Z2yCyZkM,5259
169
169
  taskflow/tests/unit/test_reducefunctor_task.py,sha256=vM4P5h80-Ex4uq2N_dNmTFL49Ks3iFmP5dMbZEk0YQ0,2106
170
- taskflow/tests/unit/test_retries.py,sha256=yRQF_TUtZ-d13sIzFNLjKZXg5DhuSj2xkhvgi8zGgCE,56542
170
+ taskflow/tests/unit/test_retries.py,sha256=xxHEBNoiaDR5WMztzm5CidqGrOkKJ2yqs2J69P1KwkE,58658
171
171
  taskflow/tests/unit/test_states.py,sha256=iYyHo9YzHBMjlYaqlzZJTcKjB53WCqf5Fw3OGoVKVME,3660
172
172
  taskflow/tests/unit/test_storage.py,sha256=SlShgJ4hirdnggDkpB3GoosY--4B0PqMOVvMBG5D6g4,23520
173
173
  taskflow/tests/unit/test_suspend.py,sha256=2d5y15Fw6NESJ4oEUAA7dosECGb2-CLkkgXULqwNtWw,10077
@@ -234,11 +234,11 @@ taskflow/utils/persistence_utils.py,sha256=GWceOcxdfsf-MtrdR74xmC2khClF8im6DpZmR
234
234
  taskflow/utils/redis_utils.py,sha256=zJBvXmlNZUQ_gwGZAaNLySVtCtou3YayHAkGSCNKDUw,4345
235
235
  taskflow/utils/schema_utils.py,sha256=Zf6eL0NK0_TVFD_Sc1yEZYswFz9K0tet1Dmj48F8uMA,1434
236
236
  taskflow/utils/threading_utils.py,sha256=eiaNUK127DOBr_zfj3-j4Oi5a2dsD7VunVeTYN6NjPo,5849
237
- taskflow-5.9.0.dist-info/AUTHORS,sha256=uKVGnRq9UrIKLl5MhXJ9QuqzKXynjWcZcuaW_j9Eh5g,4564
238
- taskflow-5.9.0.dist-info/LICENSE,sha256=0t4vVm0tDgtQn7DqH6Nmn0kGSrHeIcV0U8qzdQojTo8,10143
239
- taskflow-5.9.0.dist-info/METADATA,sha256=uVy8Ah1A3_80STYZT8cr-rNf9cKsyXq3LZ9iWOl1xpg,5146
240
- taskflow-5.9.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
241
- taskflow-5.9.0.dist-info/entry_points.txt,sha256=bIwgsxgCx_nrcv_gMhFDVffkg_r4NHX2O43iEXUKohU,1236
242
- taskflow-5.9.0.dist-info/pbr.json,sha256=N8zRLBNt6MMlT0p1-mnnHKLxcTjAeaJkxLvgOp8vZwI,47
243
- taskflow-5.9.0.dist-info/top_level.txt,sha256=PsdN41vwysesDlqHCSVVXH4mkTMdMiZFW_yHEAXiZE4,9
244
- taskflow-5.9.0.dist-info/RECORD,,
237
+ taskflow-5.9.1.dist-info/AUTHORS,sha256=uKVGnRq9UrIKLl5MhXJ9QuqzKXynjWcZcuaW_j9Eh5g,4564
238
+ taskflow-5.9.1.dist-info/LICENSE,sha256=0t4vVm0tDgtQn7DqH6Nmn0kGSrHeIcV0U8qzdQojTo8,10143
239
+ taskflow-5.9.1.dist-info/METADATA,sha256=cZHxTrZuq1RW6ZopG9g3Yf5nM1d-dIpnW0BIZy2zyoo,5146
240
+ taskflow-5.9.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
241
+ taskflow-5.9.1.dist-info/entry_points.txt,sha256=bIwgsxgCx_nrcv_gMhFDVffkg_r4NHX2O43iEXUKohU,1236
242
+ taskflow-5.9.1.dist-info/pbr.json,sha256=r6eUVJh_ZGPwgjtiFsQha4d7x0jrO255TgbBcTs1G8M,47
243
+ taskflow-5.9.1.dist-info/top_level.txt,sha256=PsdN41vwysesDlqHCSVVXH4mkTMdMiZFW_yHEAXiZE4,9
244
+ taskflow-5.9.1.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ {"git_version": "a8b48d6e", "is_release": true}
@@ -1 +0,0 @@
1
- {"git_version": "fc14510a", "is_release": true}