taskflow 5.6.0__py3-none-any.whl → 5.6.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:
@@ -161,14 +161,11 @@ class RedisJobboardTest(test.TestCase, base.BoardTestMixin):
161
161
  test_conf = {
162
162
  'username': 'default',
163
163
  'password': 'secret',
164
+ 'sentinel_kwargs': None,
164
165
  }
165
166
  mock_sentinel.assert_called_once_with(
166
167
  [('127.0.0.1', 26379), ('::1', 26379),
167
168
  ('127.0.0.2', 26379), ('localhost', 26379)],
168
- sentinel_kwargs={
169
- 'username': 'default',
170
- 'password': 'secret'
171
- },
172
169
  **test_conf)
173
170
  mock_sentinel().master_for.assert_called_once_with('mymaster')
174
171
 
@@ -179,7 +176,7 @@ class RedisJobboardTest(test.TestCase, base.BoardTestMixin):
179
176
  'password': 'secret',
180
177
  'namespace': 'test',
181
178
  'sentinel': 'mymaster',
182
- 'sentinel_kwargs': {'password': 'senitelsecret'},
179
+ 'sentinel_kwargs': None,
183
180
  'ssl': True,
184
181
  'ssl_ca_certs': '/etc/ssl/certs'}
185
182
  with mock.patch('redis.sentinel.Sentinel') as mock_sentinel:
@@ -192,6 +189,6 @@ class RedisJobboardTest(test.TestCase, base.BoardTestMixin):
192
189
  }
193
190
  mock_sentinel.assert_called_once_with(
194
191
  [('127.0.0.1', 26379)],
195
- sentinel_kwargs={'password': 'senitelsecret'},
192
+ sentinel_kwargs=None,
196
193
  **test_conf)
197
194
  mock_sentinel().master_for.assert_called_once_with('mymaster')
@@ -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
@@ -497,6 +499,56 @@ class RetryTest(utils.EngineTestBase):
497
499
  self.assertRaisesRegex(RuntimeError, '^Woot', engine.run)
498
500
  self.assertRaisesRegex(RuntimeError, '^Woot', engine.run)
499
501
 
502
+ def test_restart_reverted_unordered_flows_with_retries(self):
503
+ now = time.time()
504
+
505
+ # First flow of an unordered flow:
506
+ subflow1 = lf.Flow('subflow1')
507
+
508
+ # * a task that completes in 3 sec with a few retries
509
+ subsubflow1 = lf.Flow('subflow1.subsubflow1',
510
+ retry=utils.RetryFiveTimes())
511
+ subsubflow1.add(utils.SuccessAfter3Sec('subflow1.fail1',
512
+ inject={'start_time': now}))
513
+ subflow1.add(subsubflow1)
514
+
515
+ # * a task that fails and triggers a revert after 5 retries
516
+ subsubflow2 = lf.Flow('subflow1.subsubflow2',
517
+ retry=utils.RetryFiveTimes())
518
+ subsubflow2.add(utils.FailingTask('subflow1.fail2'))
519
+ subflow1.add(subsubflow2)
520
+
521
+ # Second flow of the unordered flow:
522
+ subflow2 = lf.Flow('subflow2')
523
+
524
+ # * a task that always fails and retries
525
+ subsubflow1 = lf.Flow('subflow2.subsubflow1',
526
+ retry=utils.AlwaysRetry())
527
+ subsubflow1.add(utils.FailingTask('subflow2.fail1'))
528
+ subflow2.add(subsubflow1)
529
+
530
+ unordered_flow = uf.Flow('unordered_flow')
531
+ unordered_flow.add(subflow1, subflow2)
532
+
533
+ # Main flow, contains a simple task and an unordered flow
534
+ flow = lf.Flow('test')
535
+ flow.add(utils.NoopTask('task1'))
536
+ flow.add(unordered_flow)
537
+
538
+ engine = self._make_engine(flow)
539
+
540
+ # This test fails when using Green threads, skipping it for now
541
+ if isinstance(engine._task_executor,
542
+ executor.ParallelGreenThreadTaskExecutor):
543
+ self.skipTest("Skipping this test when using green threads.")
544
+
545
+ with utils.CaptureListener(engine) as capturer:
546
+ self.assertRaisesRegex(exc.WrappedFailure,
547
+ '.*RuntimeError: Woot!',
548
+ engine.run)
549
+ # task1 should have been reverted
550
+ self.assertIn('task1.t REVERTED(None)', capturer.values)
551
+
500
552
  def test_run_just_retry(self):
501
553
  flow = utils.OneReturnRetry(provides='x')
502
554
  engine = self._make_engine(flow)
taskflow/tests/utils.py CHANGED
@@ -217,6 +217,32 @@ class FailingTask(ProgressingTask):
217
217
  raise RuntimeError('Woot!')
218
218
 
219
219
 
220
+ class SimpleTask(task.Task):
221
+ def execute(self, time_sleep=0, **kwargs):
222
+ time.sleep(time_sleep)
223
+
224
+
225
+ class SuccessAfter3Sec(task.Task):
226
+ def execute(self, start_time, **kwargs):
227
+ now = time.time()
228
+ if now - start_time >= 3:
229
+ return None
230
+ raise RuntimeError('Woot!')
231
+
232
+
233
+ class RetryFiveTimes(retry.Times):
234
+ def on_failure(self, history, *args, **kwargs):
235
+ if len(history) < 5:
236
+ time.sleep(1)
237
+ return retry.RETRY
238
+ return retry.REVERT_ALL
239
+
240
+
241
+ class AlwaysRetry(retry.Times):
242
+ def on_failure(self, history, *args, **kwargs):
243
+ return retry.RETRY
244
+
245
+
220
246
  class OptionalTask(task.Task):
221
247
  def execute(self, a, b=5):
222
248
  result = a * b
@@ -1,13 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: taskflow
3
- Version: 5.6.0
3
+ Version: 5.6.1
4
4
  Summary: Taskflow structured state management library.
5
5
  Home-page: https://docs.openstack.org/taskflow/latest/
6
6
  Author: OpenStack
7
7
  Author-email: openstack-discuss@lists.openstack.org
8
- License: UNKNOWN
9
8
  Keywords: reliable,tasks,execution,parallel,dataflow,workflows,distributed
10
- Platform: UNKNOWN
11
9
  Classifier: Development Status :: 5 - Production/Stable
12
10
  Classifier: Environment :: OpenStack
13
11
  Classifier: Intended Audience :: Developers
@@ -25,41 +23,43 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
25
23
  Classifier: Topic :: Software Development :: Libraries
26
24
  Classifier: Topic :: System :: Distributed Computing
27
25
  Requires-Python: >=3.8
28
- Requires-Dist: automaton (>=1.9.0)
29
- Requires-Dist: cachetools (>=2.0.0)
30
- Requires-Dist: fasteners (>=0.17.3)
31
- Requires-Dist: futurist (>=1.2.0)
32
- Requires-Dist: jsonschema (>=3.2.0)
33
- Requires-Dist: networkx (>=2.1.0)
34
- Requires-Dist: oslo.serialization (!=2.19.1,>=2.18.0)
35
- Requires-Dist: oslo.utils (>=3.33.0)
36
- Requires-Dist: pbr (!=2.1.0,>=2.0.0)
37
- Requires-Dist: pydot (>=1.2.4)
38
- Requires-Dist: stevedore (>=1.20.0)
39
- Requires-Dist: tenacity (>=6.0.0)
26
+ License-File: LICENSE
27
+ License-File: AUTHORS
28
+ Requires-Dist: pbr !=2.1.0,>=2.0.0
29
+ Requires-Dist: futurist >=1.2.0
30
+ Requires-Dist: fasteners >=0.17.3
31
+ Requires-Dist: networkx >=2.1.0
32
+ Requires-Dist: stevedore >=1.20.0
33
+ Requires-Dist: jsonschema >=3.2.0
34
+ Requires-Dist: automaton >=1.9.0
35
+ Requires-Dist: oslo.utils >=3.33.0
36
+ Requires-Dist: oslo.serialization !=2.19.1,>=2.18.0
37
+ Requires-Dist: tenacity >=6.0.0
38
+ Requires-Dist: cachetools >=2.0.0
39
+ Requires-Dist: pydot >=1.2.4
40
40
  Provides-Extra: database
41
- Requires-Dist: PyMySQL (>=0.7.6) ; extra == 'database'
42
- Requires-Dist: SQLAlchemy (!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10) ; extra == 'database'
43
- Requires-Dist: SQLAlchemy-Utils (>=0.30.11) ; extra == 'database'
44
- Requires-Dist: alembic (>=0.8.10) ; extra == 'database'
45
- Requires-Dist: psycopg2 (>=2.8.0) ; extra == 'database'
41
+ Requires-Dist: SQLAlchemy !=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10 ; extra == 'database'
42
+ Requires-Dist: alembic >=0.8.10 ; extra == 'database'
43
+ Requires-Dist: SQLAlchemy-Utils >=0.30.11 ; extra == 'database'
44
+ Requires-Dist: PyMySQL >=0.7.6 ; extra == 'database'
45
+ Requires-Dist: psycopg2 >=2.8.0 ; extra == 'database'
46
46
  Provides-Extra: eventlet
47
- Requires-Dist: eventlet (!=0.18.3,!=0.20.1,!=0.21.0,>=0.18.2) ; extra == 'eventlet'
47
+ Requires-Dist: eventlet !=0.18.3,!=0.20.1,!=0.21.0,>=0.18.2 ; extra == 'eventlet'
48
48
  Provides-Extra: redis
49
- Requires-Dist: redis (>=4.0.0) ; extra == 'redis'
49
+ Requires-Dist: redis >=4.0.0 ; extra == 'redis'
50
50
  Provides-Extra: test
51
- Requires-Dist: hacking (<0.11,>=0.10.0) ; extra == 'test'
52
- Requires-Dist: mock (>=2.0.0) ; extra == 'test'
53
- Requires-Dist: oslotest (>=3.2.0) ; extra == 'test'
54
- Requires-Dist: pydotplus (>=2.0.2) ; extra == 'test'
55
- Requires-Dist: stestr (>=2.0.0) ; extra == 'test'
56
- Requires-Dist: testscenarios (>=0.4) ; extra == 'test'
57
- Requires-Dist: testtools (>=2.2.0) ; extra == 'test'
51
+ Requires-Dist: pydotplus >=2.0.2 ; extra == 'test'
52
+ Requires-Dist: hacking <0.11,>=0.10.0 ; extra == 'test'
53
+ Requires-Dist: oslotest >=3.2.0 ; extra == 'test'
54
+ Requires-Dist: mock >=2.0.0 ; extra == 'test'
55
+ Requires-Dist: testtools >=2.2.0 ; extra == 'test'
56
+ Requires-Dist: testscenarios >=0.4 ; extra == 'test'
57
+ Requires-Dist: stestr >=2.0.0 ; extra == 'test'
58
58
  Provides-Extra: workers
59
- Requires-Dist: kombu (>=4.3.0) ; extra == 'workers'
59
+ Requires-Dist: kombu >=4.3.0 ; extra == 'workers'
60
60
  Provides-Extra: zookeeper
61
- Requires-Dist: kazoo (>=2.6.0) ; extra == 'zookeeper'
62
- Requires-Dist: zake (>=0.1.6) ; extra == 'zookeeper'
61
+ Requires-Dist: kazoo >=2.6.0 ; extra == 'zookeeper'
62
+ Requires-Dist: zake >=0.1.6 ; extra == 'zookeeper'
63
63
 
64
64
  ========================
65
65
  Team and repository tags
@@ -135,5 +135,3 @@ We also have sphinx documentation in ``docs/source``.
135
135
  .. _eventlet: http://eventlet.net/
136
136
  .. _tox: https://tox.testrun.org/
137
137
 
138
-
139
-
@@ -29,7 +29,7 @@ taskflow/engines/action_engine/deciders.py,sha256=WEKo189CL9Zdg506Sz3Mlxpfp6dqGv
29
29
  taskflow/engines/action_engine/engine.py,sha256=RCjtPkpT2_aqpuhGZb3ZSruOMZdoVEm9PXpiVDzpLZU,29532
30
30
  taskflow/engines/action_engine/executor.py,sha256=sBmKwgDQN9fEZz42T7RB-RYUZvWqfHqC-Y2EsWRGkYI,7749
31
31
  taskflow/engines/action_engine/process_executor.py,sha256=4fbJtO7XWWnCWSKBTKEMrMNi2ryZn7W6c0LT3j1w5D4,27828
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
@@ -148,7 +148,7 @@ taskflow/persistence/backends/sqlalchemy/alembic/versions/README,sha256=AwegmiWc
148
148
  taskflow/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
149
149
  taskflow/tests/fixtures.py,sha256=VfGlusX2q79_ktPME4cm1qt_gN9VNRAwyYy5sDBAX0Y,2004
150
150
  taskflow/tests/test_examples.py,sha256=g2zhguLKE4Tex2e_vSmKMhsNXItnKWj89_VbnmgGejU,4925
151
- taskflow/tests/utils.py,sha256=P6RPD2w5h00KAse7r31LC9tJils0jaeiUx5QiVqLOA0,11157
151
+ taskflow/tests/utils.py,sha256=Xa1o6x6LnOWtNa_eNXmOrMZPcdr2hmo4f_MJF-D5Xa4,11788
152
152
  taskflow/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
153
  taskflow/tests/unit/test_arguments_passing.py,sha256=gEtOSx9fibT_peqqWhtqCY96P1AJjaCEo3Hry0qdPak,9204
154
154
  taskflow/tests/unit/test_check_transition.py,sha256=DuxJAErCwheWPAdN_43LOOvZg00vmUoC-IzGgh642IM,6173
@@ -166,7 +166,7 @@ taskflow/tests/unit/test_mapfunctor_task.py,sha256=1FI8AJxRUPxT7Lu6h9Mhd62srAnKf
166
166
  taskflow/tests/unit/test_notifier.py,sha256=Q4xGl9e_LZRiJVpGR2FbG2qSp9CqlP65aDsaIKxPqHI,7894
167
167
  taskflow/tests/unit/test_progress.py,sha256=oeYFeWuHde1D2cAahhE1yN1NznNcXk7ajw0Z2yCyZkM,5259
168
168
  taskflow/tests/unit/test_reducefunctor_task.py,sha256=vM4P5h80-Ex4uq2N_dNmTFL49Ks3iFmP5dMbZEk0YQ0,2106
169
- taskflow/tests/unit/test_retries.py,sha256=UBYPtjTwydx7FnMuwYzYQOWta8bh8qtaA2tkEMqDhHE,56365
169
+ taskflow/tests/unit/test_retries.py,sha256=KDZbF-eWNKGvD-ezNRG--Pnbj9-5RCKBzuvpgvWtm38,58481
170
170
  taskflow/tests/unit/test_states.py,sha256=iYyHo9YzHBMjlYaqlzZJTcKjB53WCqf5Fw3OGoVKVME,3660
171
171
  taskflow/tests/unit/test_storage.py,sha256=SlShgJ4hirdnggDkpB3GoosY--4B0PqMOVvMBG5D6g4,23520
172
172
  taskflow/tests/unit/test_suspend.py,sha256=j4M5J2G1aoGUJb111_xUUb0oYJfgRo9hC4ZFyr-00d4,9900
@@ -187,7 +187,7 @@ taskflow/tests/unit/action_engine/test_scoping.py,sha256=wIB9C3LMgfsqO6cdz_ZdhQc
187
187
  taskflow/tests/unit/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
188
188
  taskflow/tests/unit/jobs/base.py,sha256=wYv5ziDeVdYn2nhuMSfYTWU39Xxpv8lRKvJbGsB79lM,8447
189
189
  taskflow/tests/unit/jobs/test_entrypoint.py,sha256=t2m5zeYhjb2pmPxBgGO_0AMWR0dabWxglDBODzLE0fY,2220
190
- taskflow/tests/unit/jobs/test_redis_job.py,sha256=Ko8s96Sr8ilRUe6p_yybZUKs5FVTiRl0nMERMJswy2M,7540
190
+ taskflow/tests/unit/jobs/test_redis_job.py,sha256=wHwptqgrafZMk0aDZNvn2h3sJw8ckKY1g5J9I_dzWAM,7394
191
191
  taskflow/tests/unit/jobs/test_zk_job.py,sha256=e5CdkqmiQY_jzNtcHsxKcsS9uY7k-D8CMGkqt1J_bqE,13789
192
192
  taskflow/tests/unit/patterns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
193
193
  taskflow/tests/unit/patterns/test_graph_flow.py,sha256=g5x6RdEgD6Sws3C5zmgz3kFpbJLEoi6i42RSEk5Vlso,12452
@@ -232,11 +232,11 @@ taskflow/utils/persistence_utils.py,sha256=GWceOcxdfsf-MtrdR74xmC2khClF8im6DpZmR
232
232
  taskflow/utils/redis_utils.py,sha256=zJBvXmlNZUQ_gwGZAaNLySVtCtou3YayHAkGSCNKDUw,4345
233
233
  taskflow/utils/schema_utils.py,sha256=Zf6eL0NK0_TVFD_Sc1yEZYswFz9K0tet1Dmj48F8uMA,1434
234
234
  taskflow/utils/threading_utils.py,sha256=eiaNUK127DOBr_zfj3-j4Oi5a2dsD7VunVeTYN6NjPo,5849
235
- taskflow-5.6.0.dist-info/AUTHORS,sha256=tle5nZW61YeKYzeIWT7GN7FJ6_Y0UkBX_oYE2tDMgKc,4530
236
- taskflow-5.6.0.dist-info/LICENSE,sha256=0t4vVm0tDgtQn7DqH6Nmn0kGSrHeIcV0U8qzdQojTo8,10143
237
- taskflow-5.6.0.dist-info/METADATA,sha256=4sOTaS700K8VJhSUNMhUUPNhbK99iEZGRPmGbz2cFkM,5150
238
- taskflow-5.6.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
239
- taskflow-5.6.0.dist-info/entry_points.txt,sha256=MGjjnng_YpSJs9BMAJBC2hJnljMV0pNllXl_5VoHJV0,1183
240
- taskflow-5.6.0.dist-info/pbr.json,sha256=sOEouTVPek9jsny8UcBxoKL_PTvTR-_fZPHqbhIepFk,47
241
- taskflow-5.6.0.dist-info/top_level.txt,sha256=PsdN41vwysesDlqHCSVVXH4mkTMdMiZFW_yHEAXiZE4,9
242
- taskflow-5.6.0.dist-info/RECORD,,
235
+ taskflow-5.6.1.dist-info/AUTHORS,sha256=tle5nZW61YeKYzeIWT7GN7FJ6_Y0UkBX_oYE2tDMgKc,4530
236
+ taskflow-5.6.1.dist-info/LICENSE,sha256=0t4vVm0tDgtQn7DqH6Nmn0kGSrHeIcV0U8qzdQojTo8,10143
237
+ taskflow-5.6.1.dist-info/METADATA,sha256=nco8fLkosHJgz7lS1aYOynkN2NNEriO5IChcSEgK8_8,5099
238
+ taskflow-5.6.1.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
239
+ taskflow-5.6.1.dist-info/entry_points.txt,sha256=XtpPeEh52QgJ7IOy68z7_5nSrohCjhbpHwN3bgyNqqg,1182
240
+ taskflow-5.6.1.dist-info/pbr.json,sha256=9rNV-0TqLzQMcCdjF-v7Gpa2IE6IPtss5GhuoO-4RSg,47
241
+ taskflow-5.6.1.dist-info/top_level.txt,sha256=PsdN41vwysesDlqHCSVVXH4mkTMdMiZFW_yHEAXiZE4,9
242
+ taskflow-5.6.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: setuptools (75.3.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -21,4 +21,3 @@ mysql = taskflow.persistence.backends.impl_sqlalchemy:SQLAlchemyBackend
21
21
  postgresql = taskflow.persistence.backends.impl_sqlalchemy:SQLAlchemyBackend
22
22
  sqlite = taskflow.persistence.backends.impl_sqlalchemy:SQLAlchemyBackend
23
23
  zookeeper = taskflow.persistence.backends.impl_zookeeper:ZkBackend
24
-
@@ -0,0 +1 @@
1
+ {"git_version": "24c88865", "is_release": true}
@@ -1 +0,0 @@
1
- {"git_version": "39440b74", "is_release": true}