python-saga-orchestrator 0.1.2__tar.gz → 0.1.4__tar.gz
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.
- {python_saga_orchestrator-0.1.2/python_saga_orchestrator.egg-info → python_saga_orchestrator-0.1.4}/PKG-INFO +20 -1
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/README.md +19 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/pyproject.toml +1 -1
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4/python_saga_orchestrator.egg-info}/PKG-INFO +20 -1
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/python_saga_orchestrator.egg-info/SOURCES.txt +11 -1
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/__init__.py +46 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/core/engine.py +300 -28
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/core/orchestrator.py +49 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/__init__.py +2 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/notify.py +1 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/step.py +42 -7
- python_saga_orchestrator-0.1.4/saga_orchestrator/inbox/__init__.py +27 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/inbox/contracts.py +81 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/inbox/dispatcher.py +120 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/inbox/models.py +84 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/inbox/repository.py +165 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/inbox/retry.py +20 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/outbox/__init__.py +33 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/outbox/contracts.py +87 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/outbox/dispatcher.py +84 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/outbox/factory.py +62 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/outbox/repository.py +154 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/outbox/retry.py +20 -0
- python_saga_orchestrator-0.1.4/saga_orchestrator/outbox/serialization.py +47 -0
- python_saga_orchestrator-0.1.2/saga_orchestrator/outbox/__init__.py +0 -15
- python_saga_orchestrator-0.1.2/saga_orchestrator/outbox/dispatcher.py +0 -95
- python_saga_orchestrator-0.1.2/saga_orchestrator/outbox/repository.py +0 -73
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/LICENSE +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/python_saga_orchestrator.egg-info/dependency_links.txt +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/python_saga_orchestrator.egg-info/requires.txt +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/python_saga_orchestrator.egg-info/top_level.txt +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/admin/__init__.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/admin/api.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/core/__init__.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/core/builder.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/core/repository.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/__init__.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/exceptions/__init__.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/exceptions/saga.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/mixins/__init__.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/mixins/saga_state.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/builder.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/enums/__init__.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/enums/saga_status.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/retry.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/domain/models/saga_snapshot.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/outbox/event.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/outbox/models.py +0 -0
- {python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-saga-orchestrator
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Lightweight embedded saga orchestrator for asyncio Python services
|
|
5
5
|
Author-email: Maxim Vasilyev <mayxis@inbox.ru>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -51,6 +51,7 @@ Unlike external workflow platforms, this library runs inside your service and st
|
|
|
51
51
|
- persisted saga state through `SagaStateMixin`
|
|
52
52
|
- runtime execution through `SagaOrchestrator` and `SagaEngine`
|
|
53
53
|
- retry, timeout, recovery, and compensation
|
|
54
|
+
- async queue-style steps through `StepAwaitEvent` and `notify(...)`
|
|
54
55
|
- administrative operations through `SagaAdmin`
|
|
55
56
|
- PostgreSQL-first reliability using `SELECT ... FOR UPDATE`
|
|
56
57
|
|
|
@@ -277,6 +278,23 @@ token = await orchestrator.await_event(
|
|
|
277
278
|
|
|
278
279
|
The event payload is stored in saga context and can be used by root-step `input_map` functions through `InputContext`.
|
|
279
280
|
|
|
281
|
+
For distributed consumers, use transactional inbox ingestion first, then process inbox rows:
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
stored = await orchestrator.ingest_event(
|
|
285
|
+
aggregation_id="order-123",
|
|
286
|
+
event={
|
|
287
|
+
"event_id": "evt-123",
|
|
288
|
+
"event_type": "payment.completed",
|
|
289
|
+
"correlation_id": "corr-123",
|
|
290
|
+
"payload": {"payment_id": "pay-1"},
|
|
291
|
+
},
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
if stored:
|
|
295
|
+
await orchestrator.run_inbox_due(limit=100)
|
|
296
|
+
```
|
|
297
|
+
|
|
280
298
|
## Administrative operations
|
|
281
299
|
|
|
282
300
|
Get the full persisted state:
|
|
@@ -334,6 +352,7 @@ A runnable end-to-end example is available in:
|
|
|
334
352
|
- [`examples/retry_recovery.py`](./examples/retry_recovery.py)
|
|
335
353
|
- [`examples/compensation_flow.py`](./examples/compensation_flow.py)
|
|
336
354
|
- [`examples/admin_skip.py`](./examples/admin_skip.py)
|
|
355
|
+
- [`examples/http_and_queue.py`](./examples/http_and_queue.py)
|
|
337
356
|
|
|
338
357
|
These examples demonstrate:
|
|
339
358
|
- basic model deployment
|
|
@@ -17,6 +17,7 @@ Unlike external workflow platforms, this library runs inside your service and st
|
|
|
17
17
|
- persisted saga state through `SagaStateMixin`
|
|
18
18
|
- runtime execution through `SagaOrchestrator` and `SagaEngine`
|
|
19
19
|
- retry, timeout, recovery, and compensation
|
|
20
|
+
- async queue-style steps through `StepAwaitEvent` and `notify(...)`
|
|
20
21
|
- administrative operations through `SagaAdmin`
|
|
21
22
|
- PostgreSQL-first reliability using `SELECT ... FOR UPDATE`
|
|
22
23
|
|
|
@@ -243,6 +244,23 @@ token = await orchestrator.await_event(
|
|
|
243
244
|
|
|
244
245
|
The event payload is stored in saga context and can be used by root-step `input_map` functions through `InputContext`.
|
|
245
246
|
|
|
247
|
+
For distributed consumers, use transactional inbox ingestion first, then process inbox rows:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
stored = await orchestrator.ingest_event(
|
|
251
|
+
aggregation_id="order-123",
|
|
252
|
+
event={
|
|
253
|
+
"event_id": "evt-123",
|
|
254
|
+
"event_type": "payment.completed",
|
|
255
|
+
"correlation_id": "corr-123",
|
|
256
|
+
"payload": {"payment_id": "pay-1"},
|
|
257
|
+
},
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
if stored:
|
|
261
|
+
await orchestrator.run_inbox_due(limit=100)
|
|
262
|
+
```
|
|
263
|
+
|
|
246
264
|
## Administrative operations
|
|
247
265
|
|
|
248
266
|
Get the full persisted state:
|
|
@@ -300,6 +318,7 @@ A runnable end-to-end example is available in:
|
|
|
300
318
|
- [`examples/retry_recovery.py`](./examples/retry_recovery.py)
|
|
301
319
|
- [`examples/compensation_flow.py`](./examples/compensation_flow.py)
|
|
302
320
|
- [`examples/admin_skip.py`](./examples/admin_skip.py)
|
|
321
|
+
- [`examples/http_and_queue.py`](./examples/http_and_queue.py)
|
|
303
322
|
|
|
304
323
|
These examples demonstrate:
|
|
305
324
|
- basic model deployment
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-saga-orchestrator"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.4"
|
|
8
8
|
description = "Lightweight embedded saga orchestrator for asyncio Python services"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-saga-orchestrator
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Lightweight embedded saga orchestrator for asyncio Python services
|
|
5
5
|
Author-email: Maxim Vasilyev <mayxis@inbox.ru>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -51,6 +51,7 @@ Unlike external workflow platforms, this library runs inside your service and st
|
|
|
51
51
|
- persisted saga state through `SagaStateMixin`
|
|
52
52
|
- runtime execution through `SagaOrchestrator` and `SagaEngine`
|
|
53
53
|
- retry, timeout, recovery, and compensation
|
|
54
|
+
- async queue-style steps through `StepAwaitEvent` and `notify(...)`
|
|
54
55
|
- administrative operations through `SagaAdmin`
|
|
55
56
|
- PostgreSQL-first reliability using `SELECT ... FOR UPDATE`
|
|
56
57
|
|
|
@@ -277,6 +278,23 @@ token = await orchestrator.await_event(
|
|
|
277
278
|
|
|
278
279
|
The event payload is stored in saga context and can be used by root-step `input_map` functions through `InputContext`.
|
|
279
280
|
|
|
281
|
+
For distributed consumers, use transactional inbox ingestion first, then process inbox rows:
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
stored = await orchestrator.ingest_event(
|
|
285
|
+
aggregation_id="order-123",
|
|
286
|
+
event={
|
|
287
|
+
"event_id": "evt-123",
|
|
288
|
+
"event_type": "payment.completed",
|
|
289
|
+
"correlation_id": "corr-123",
|
|
290
|
+
"payload": {"payment_id": "pay-1"},
|
|
291
|
+
},
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
if stored:
|
|
295
|
+
await orchestrator.run_inbox_due(limit=100)
|
|
296
|
+
```
|
|
297
|
+
|
|
280
298
|
## Administrative operations
|
|
281
299
|
|
|
282
300
|
Get the full persisted state:
|
|
@@ -334,6 +352,7 @@ A runnable end-to-end example is available in:
|
|
|
334
352
|
- [`examples/retry_recovery.py`](./examples/retry_recovery.py)
|
|
335
353
|
- [`examples/compensation_flow.py`](./examples/compensation_flow.py)
|
|
336
354
|
- [`examples/admin_skip.py`](./examples/admin_skip.py)
|
|
355
|
+
- [`examples/http_and_queue.py`](./examples/http_and_queue.py)
|
|
337
356
|
|
|
338
357
|
These examples demonstrate:
|
|
339
358
|
- basic model deployment
|
|
@@ -27,8 +27,18 @@ saga_orchestrator/domain/models/saga_snapshot.py
|
|
|
27
27
|
saga_orchestrator/domain/models/step.py
|
|
28
28
|
saga_orchestrator/domain/models/enums/__init__.py
|
|
29
29
|
saga_orchestrator/domain/models/enums/saga_status.py
|
|
30
|
+
saga_orchestrator/inbox/__init__.py
|
|
31
|
+
saga_orchestrator/inbox/contracts.py
|
|
32
|
+
saga_orchestrator/inbox/dispatcher.py
|
|
33
|
+
saga_orchestrator/inbox/models.py
|
|
34
|
+
saga_orchestrator/inbox/repository.py
|
|
35
|
+
saga_orchestrator/inbox/retry.py
|
|
30
36
|
saga_orchestrator/outbox/__init__.py
|
|
37
|
+
saga_orchestrator/outbox/contracts.py
|
|
31
38
|
saga_orchestrator/outbox/dispatcher.py
|
|
32
39
|
saga_orchestrator/outbox/event.py
|
|
40
|
+
saga_orchestrator/outbox/factory.py
|
|
33
41
|
saga_orchestrator/outbox/models.py
|
|
34
|
-
saga_orchestrator/outbox/repository.py
|
|
42
|
+
saga_orchestrator/outbox/repository.py
|
|
43
|
+
saga_orchestrator/outbox/retry.py
|
|
44
|
+
saga_orchestrator/outbox/serialization.py
|
{python_saga_orchestrator-0.1.2 → python_saga_orchestrator-0.1.4}/saga_orchestrator/__init__.py
RENAMED
|
@@ -24,37 +24,82 @@ from .domain.models import (
|
|
|
24
24
|
SagaAdminSnapshot,
|
|
25
25
|
SagaDefinition,
|
|
26
26
|
SagaSnapshot,
|
|
27
|
+
StepAwaitEvent,
|
|
27
28
|
StepDefinition,
|
|
28
29
|
StepInputMap,
|
|
29
30
|
StepRef,
|
|
30
31
|
)
|
|
31
32
|
from .domain.models.enums import SagaStatus
|
|
33
|
+
from .inbox import (
|
|
34
|
+
ClaimedInboxMessage,
|
|
35
|
+
FixedInboxRetry,
|
|
36
|
+
InboxDispatcher,
|
|
37
|
+
InboxMessageMixin,
|
|
38
|
+
InboxProcessor,
|
|
39
|
+
InboxProcessOutcome,
|
|
40
|
+
InboxProcessStatus,
|
|
41
|
+
InboxRepository,
|
|
42
|
+
InboxRetryPolicy,
|
|
43
|
+
InboxStatus,
|
|
44
|
+
InboxWriteMessage,
|
|
45
|
+
InboxWriter,
|
|
46
|
+
)
|
|
32
47
|
from .outbox import (
|
|
48
|
+
ClaimedOutboxMessage,
|
|
49
|
+
DefaultOutboxMessageFactory,
|
|
50
|
+
FixedOutboxDispatchRetry,
|
|
51
|
+
JsonOutboxSerializer,
|
|
33
52
|
OutboxDispatcher,
|
|
53
|
+
OutboxDispatchRetryPolicy,
|
|
34
54
|
OutboxEvent,
|
|
55
|
+
OutboxMessageFactory,
|
|
35
56
|
OutboxMessageMixin,
|
|
36
57
|
OutboxPublisher,
|
|
37
58
|
OutboxRepository,
|
|
59
|
+
OutboxSerializer,
|
|
38
60
|
OutboxStatus,
|
|
61
|
+
OutboxWriteMessage,
|
|
62
|
+
OutboxWriter,
|
|
39
63
|
)
|
|
40
64
|
|
|
41
65
|
__all__ = [
|
|
42
66
|
"ActiveSagaAlreadyExistsError",
|
|
43
67
|
"AwaitingEvent",
|
|
44
68
|
"BaseStep",
|
|
69
|
+
"ClaimedInboxMessage",
|
|
70
|
+
"ClaimedOutboxMessage",
|
|
71
|
+
"DefaultOutboxMessageFactory",
|
|
45
72
|
"ExponentialRetry",
|
|
73
|
+
"FixedInboxRetry",
|
|
74
|
+
"FixedOutboxDispatchRetry",
|
|
46
75
|
"FixedRetry",
|
|
76
|
+
"InboxDispatcher",
|
|
77
|
+
"InboxMessageMixin",
|
|
78
|
+
"InboxProcessOutcome",
|
|
79
|
+
"InboxProcessStatus",
|
|
80
|
+
"InboxProcessor",
|
|
81
|
+
"InboxRepository",
|
|
82
|
+
"InboxRetryPolicy",
|
|
83
|
+
"InboxStatus",
|
|
84
|
+
"InboxWriteMessage",
|
|
85
|
+
"InboxWriter",
|
|
47
86
|
"InputContext",
|
|
87
|
+
"JsonOutboxSerializer",
|
|
48
88
|
"NotifyEvent",
|
|
49
89
|
"NotifyResult",
|
|
50
90
|
"NoRetry",
|
|
51
91
|
"OutboxDispatcher",
|
|
92
|
+
"OutboxDispatchRetryPolicy",
|
|
52
93
|
"OutboxEvent",
|
|
94
|
+
"OutboxMessageFactory",
|
|
53
95
|
"OutboxMap",
|
|
54
96
|
"OutboxMessageMixin",
|
|
55
97
|
"OutboxPublisher",
|
|
56
98
|
"OutboxRepository",
|
|
99
|
+
"OutboxSerializer",
|
|
57
100
|
"OutboxStatus",
|
|
101
|
+
"OutboxWriteMessage",
|
|
102
|
+
"OutboxWriter",
|
|
58
103
|
"RetryPolicy",
|
|
59
104
|
"SagaAdmin",
|
|
60
105
|
"SagaAdminSnapshot",
|
|
@@ -70,6 +115,7 @@ __all__ = [
|
|
|
70
115
|
"SagaStateMixin",
|
|
71
116
|
"SagaStatus",
|
|
72
117
|
"StepDefinition",
|
|
118
|
+
"StepAwaitEvent",
|
|
73
119
|
"StepInputMap",
|
|
74
120
|
"StepRef",
|
|
75
121
|
"TypeValidationError",
|