papyra 0.1.0__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.
Files changed (68) hide show
  1. papyra-0.1.0/.gitignore +31 -0
  2. papyra-0.1.0/LICENSE +11 -0
  3. papyra-0.1.0/PKG-INFO +305 -0
  4. papyra-0.1.0/README.md +251 -0
  5. papyra-0.1.0/papyra/__init__.py +47 -0
  6. papyra-0.1.0/papyra/_envelope.py +123 -0
  7. papyra-0.1.0/papyra/actor.py +162 -0
  8. papyra-0.1.0/papyra/address.py +109 -0
  9. papyra-0.1.0/papyra/audit.py +115 -0
  10. papyra-0.1.0/papyra/cli/__init__.py +0 -0
  11. papyra-0.1.0/papyra/cli/app.py +34 -0
  12. papyra-0.1.0/papyra/cli/doctor/__init__.py +0 -0
  13. papyra-0.1.0/papyra/cli/doctor/app.py +131 -0
  14. papyra-0.1.0/papyra/cli/inspect/__init__.py +0 -0
  15. papyra-0.1.0/papyra/cli/inspect/app.py +146 -0
  16. papyra-0.1.0/papyra/cli/metrics/__init__.py +0 -0
  17. papyra-0.1.0/papyra/cli/metrics/app.py +113 -0
  18. papyra-0.1.0/papyra/cli/persistence/__init__.py +0 -0
  19. papyra-0.1.0/papyra/cli/persistence/app.py +367 -0
  20. papyra-0.1.0/papyra/conf/__init__.py +79 -0
  21. papyra-0.1.0/papyra/conf/global_settings.py +276 -0
  22. papyra-0.1.0/papyra/context.py +138 -0
  23. papyra-0.1.0/papyra/contrib/__init__.py +0 -0
  24. papyra-0.1.0/papyra/contrib/asgi/__ini__.py +10 -0
  25. papyra-0.1.0/papyra/contrib/asgi/endpoints.py +205 -0
  26. papyra-0.1.0/papyra/contrib/asgi/lifesycle.py +68 -0
  27. papyra-0.1.0/papyra/contrib/asgi/types.py +34 -0
  28. papyra-0.1.0/papyra/contrib/fastapi/__init__.py +3 -0
  29. papyra-0.1.0/papyra/contrib/fastapi/integration.py +96 -0
  30. papyra-0.1.0/papyra/contrib/lilya/__init__.py +3 -0
  31. papyra-0.1.0/papyra/contrib/lilya/integration.py +96 -0
  32. papyra-0.1.0/papyra/contrib/ravyn/__init__.py +3 -0
  33. papyra-0.1.0/papyra/contrib/ravyn/integration.py +97 -0
  34. papyra-0.1.0/papyra/contrib/starlette/__init__.py +3 -0
  35. papyra-0.1.0/papyra/contrib/starlette/integration.py +96 -0
  36. papyra-0.1.0/papyra/events.py +182 -0
  37. papyra-0.1.0/papyra/exceptions.py +64 -0
  38. papyra-0.1.0/papyra/hooks.py +196 -0
  39. papyra-0.1.0/papyra/logging.py +214 -0
  40. papyra-0.1.0/papyra/mailbox.py +110 -0
  41. papyra-0.1.0/papyra/monkay.py +41 -0
  42. papyra-0.1.0/papyra/persistence/__init__.py +31 -0
  43. papyra-0.1.0/papyra/persistence/_retention.py +71 -0
  44. papyra-0.1.0/papyra/persistence/_utils.py +63 -0
  45. papyra-0.1.0/papyra/persistence/backends/__init__.py +0 -0
  46. papyra-0.1.0/papyra/persistence/backends/memory.py +304 -0
  47. papyra-0.1.0/papyra/persistence/backends/redis.py +1099 -0
  48. papyra-0.1.0/papyra/persistence/backends/retention.py +30 -0
  49. papyra-0.1.0/papyra/persistence/backends/rotating.py +833 -0
  50. papyra-0.1.0/papyra/persistence/base.py +170 -0
  51. papyra-0.1.0/papyra/persistence/contract.py +186 -0
  52. papyra-0.1.0/papyra/persistence/json.py +583 -0
  53. papyra-0.1.0/papyra/persistence/metrics.py +234 -0
  54. papyra-0.1.0/papyra/persistence/models.py +243 -0
  55. papyra-0.1.0/papyra/persistence/startup.py +57 -0
  56. papyra-0.1.0/papyra/protocols/__init__.py +0 -0
  57. papyra-0.1.0/papyra/protocols/logging.py +74 -0
  58. papyra-0.1.0/papyra/protocols/serializer.py +12 -0
  59. papyra-0.1.0/papyra/py.typed +1 -0
  60. papyra-0.1.0/papyra/ref.py +173 -0
  61. papyra-0.1.0/papyra/serializers.py +143 -0
  62. papyra-0.1.0/papyra/supervision.py +60 -0
  63. papyra-0.1.0/papyra/supervisor.py +38 -0
  64. papyra-0.1.0/papyra/system.py +1692 -0
  65. papyra-0.1.0/papyra/typing.py +85 -0
  66. papyra-0.1.0/papyra/utils/__init__.py +0 -0
  67. papyra-0.1.0/papyra/utils/logging.py +79 -0
  68. papyra-0.1.0/pyproject.toml +187 -0
@@ -0,0 +1,31 @@
1
+ # folders
2
+ *.egg-info/
3
+ .hypothesis/
4
+ .idea/
5
+ .mypy_cache/
6
+ .pytest_cache/
7
+ .scannerwork/
8
+ .tox/
9
+ .venv/
10
+ .vscode/
11
+ __pycache__/
12
+ virtualenv/
13
+ build/
14
+ dist/
15
+ node_modules/
16
+ results/
17
+ site/
18
+ site_lang/
19
+ target/
20
+
21
+ # files
22
+ **/*.so
23
+ **/*.sqlite
24
+ *.iml
25
+ **/*_test*
26
+ .DS_Store
27
+ .coverage
28
+ .coverage.*
29
+ .python-version
30
+ coverage.*
31
+ example.sqlite
papyra-0.1.0/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Copyright © 2025, Tiago Silva. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
papyra-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,305 @@
1
+ Metadata-Version: 2.4
2
+ Name: papyra
3
+ Version: 0.1.0
4
+ Summary: The async actor model you didn't know you needed
5
+ Project-URL: Homepage, https://github.com/dymmond/papyra
6
+ Project-URL: Documentation, https://papyra.dymmond.com
7
+ Project-URL: Changelog, https://papyra.dymmond.com/release-notes/
8
+ Project-URL: Funding, https://github.com/sponsors/tarsil
9
+ Project-URL: Source, https://github.com/dymmond/papyra
10
+ Author-email: Tiago Silva <tiago@tarsild.io>
11
+ License-File: LICENSE
12
+ Keywords: actor,actor-system,asgi,async,concurrency,distributed-systems,papyra
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Framework :: AnyIO
16
+ Classifier: Framework :: AsyncIO
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Intended Audience :: Information Technology
19
+ Classifier: Intended Audience :: System Administrators
20
+ Classifier: License :: OSI Approved :: BSD License
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: Programming Language :: Python
23
+ Classifier: Programming Language :: Python :: 3
24
+ Classifier: Programming Language :: Python :: 3 :: Only
25
+ Classifier: Programming Language :: Python :: 3.10
26
+ Classifier: Programming Language :: Python :: 3.11
27
+ Classifier: Programming Language :: Python :: 3.12
28
+ Classifier: Programming Language :: Python :: 3.13
29
+ Classifier: Programming Language :: Python :: 3.14
30
+ Classifier: Topic :: Internet
31
+ Classifier: Topic :: Internet :: WWW/HTTP
32
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
33
+ Classifier: Topic :: Software Development
34
+ Classifier: Topic :: Software Development :: Libraries
35
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
36
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
37
+ Classifier: Typing :: Typed
38
+ Requires-Python: >=3.10
39
+ Requires-Dist: anyio>=4.12.0
40
+ Requires-Dist: sayer>=0.7.5
41
+ Provides-Extra: redis
42
+ Requires-Dist: redis>=7.1.0; extra == 'redis'
43
+ Provides-Extra: testing
44
+ Requires-Dist: autoflake<3.0.0,>=2.0.2; extra == 'testing'
45
+ Requires-Dist: black<25.0,==24.1.1; extra == 'testing'
46
+ Requires-Dist: fastapi; extra == 'testing'
47
+ Requires-Dist: httpx; extra == 'testing'
48
+ Requires-Dist: ipdb; extra == 'testing'
49
+ Requires-Dist: isort<6.0.0,>=5.12.0; extra == 'testing'
50
+ Requires-Dist: pytest-cov<5.0.0,>=4.0.0; extra == 'testing'
51
+ Requires-Dist: pytest<9.0.0,>=7.2.2; extra == 'testing'
52
+ Requires-Dist: ravyn; extra == 'testing'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # Papyra
56
+
57
+ <p align="center">
58
+ <a href="https://papyra.dymmond.com"><img src="https://res.cloudinary.com/dymmond/image/upload/v1768380322/Papyra/logo_wgunlg.png" alt='Papyra'></a>
59
+ </p>
60
+
61
+ <p align="center">
62
+ <em>Durable persistence, retention and compaction for actor systems</em>
63
+ </p>
64
+
65
+ <p align="center">
66
+ <a href="https://github.com/dymmond/papyra/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" target="_blank">
67
+ <img src="https://github.com/dymmond/papyra/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" alt="Test Suite">
68
+ </a>
69
+
70
+ <a href="https://pypi.org/project/papyra" target="_blank">
71
+ <img src="https://img.shields.io/pypi/v/papyra?color=%2334D058&label=pypi%20package" alt="Package version">
72
+ </a>
73
+
74
+ <a href="https://pypi.org/project/papyra" target="_blank">
75
+ <img src="https://img.shields.io/pypi/pyversions/papyra.svg?color=%2334D058" alt="Supported Python versions">
76
+ </a>
77
+ </p>
78
+
79
+ ---
80
+
81
+ **Documentation**: [https://papyra.dymmond.com](https://papyra.dymmond.com) 📚
82
+
83
+ **Source Code**: [https://github.com/dymmond/papyra](https://github.com/dymmond/papyra)
84
+
85
+ **The official supported version is always the latest released**.
86
+
87
+ ---
88
+
89
+ **Durable persistence, retention, recovery, and observability for actor systems.**
90
+
91
+ Papyra is a production-grade persistence layer designed specifically for **actor-based runtimes**.
92
+ It provides **durable system history**, **audits**, **dead-letter tracking**, **retention + compaction**,
93
+ **startup health checks**, **recovery orchestration**, and **operational tooling**.
94
+
95
+ > Papyra is not an actor framework.
96
+ > It's the **persistence and observability backbone** that makes an actor system operationally safe.
97
+
98
+ ---
99
+
100
+ ## Why Papyra?
101
+
102
+ Actor systems are excellent at concurrency and fault isolation, but production operators eventually need:
103
+
104
+ - A durable history of lifecycle events (start/stop/crash/restart)
105
+ - Audit snapshots for “what's running and what's broken?”
106
+ - Dead letters for undeliverable messages
107
+ - Retention to prevent unbounded growth
108
+ - Compaction to physically reclaim disk space
109
+ - Startup checks and deterministic recovery
110
+ - Metrics for observability
111
+ - CLI tools for real-world operations
112
+
113
+ Papyra solves this **explicitly** and safely.
114
+
115
+ ---
116
+
117
+ ## Features
118
+
119
+ ### 🧱 Persistence backends
120
+
121
+ - **JSON NDJSON file** backend (simple, readable, portable)
122
+ - **Rotating files** backend (bounded disk usage)
123
+ - **Redis Streams** backend (production, distributed, consumer-groups)
124
+ - **In-memory** backend (tests, ephemeral)
125
+
126
+ ### ♻️ Retention & compaction
127
+
128
+ - Record-count, age, and size-based retention
129
+ - Explicit **physical compaction / vacuum**
130
+ - Crash-safe atomic rewrite semantics where applicable
131
+
132
+ ### 🩺 Health, startup checks & recovery
133
+
134
+ - Scan for corruption / anomalies
135
+ - Recovery modes: **IGNORE / REPAIR / QUARANTINE**
136
+ - Startup orchestration to guarantee a clean persistence layer before actors start
137
+
138
+ ### 📊 Metrics & integration
139
+
140
+ - Backend metrics (writes, errors, scans, recoveries, compactions)
141
+ - CLI metrics output
142
+ - Optional OpenTelemetry integration
143
+
144
+ ### 🛠️ CLI
145
+
146
+ - `persistence scan | recover | compact | inspect | startup-check`
147
+ - `doctor run`
148
+ - `inspect events | audits | dead-letters | summary`
149
+ - `metrics …`
150
+
151
+ ---
152
+
153
+ ## Installation
154
+
155
+ ```bash
156
+ pip install papyra
157
+ ```
158
+
159
+ Optional extras:
160
+
161
+ ```bash
162
+ pip install papyra[redis]
163
+ ```
164
+
165
+ ---
166
+
167
+ ## ActorSystem + Papyra: the mental model
168
+
169
+ An `ActorSystem` emits **observable facts** while it runs:
170
+
171
+ - **Events**: lifecycle transitions (started, stopped, crashed, restarted)
172
+ - **Audits**: point-in-time health snapshots (counts, registry status, dead letters)
173
+ - **Dead letters**: messages that couldn't be delivered
174
+
175
+ Papyra persists these facts using the configured backend.
176
+
177
+ A key guarantee: **startup checks happen before any actor is allowed to run**.
178
+ If the persistence layer is corrupted and startup mode is strict, `ActorSystem.start()` fails.
179
+
180
+ ---
181
+
182
+ ## Quickstart (with ActorSystem)
183
+
184
+ ### 1) Pick a persistence backend
185
+
186
+ #### JSON file backend
187
+
188
+ ```python
189
+ from papyra.persistence.json import JsonFilePersistence
190
+
191
+ persistence = JsonFilePersistence("./papyra.ndjson")
192
+ ```
193
+
194
+ #### Redis Streams backend
195
+
196
+ ```python
197
+ from papyra.persistence.backends.redis import RedisStreamsConfig, RedisStreamsPersistence
198
+
199
+ persistence = RedisStreamsPersistence(
200
+ RedisStreamsConfig(url="redis://localhost:6379/0", prefix="papyra", system_id="local")
201
+ )
202
+ ```
203
+
204
+ ### 2) Start the ActorSystem with startup checks
205
+
206
+ ```python
207
+ from papyra.system import ActorSystem
208
+ from papyra.persistence.startup import PersistenceStartupConfig, PersistenceStartupMode
209
+ from papyra.persistence.models import PersistenceRecoveryConfig, PersistenceRecoveryMode
210
+
211
+ system = ActorSystem(
212
+ persistence=persistence,
213
+ # Ensure the persistence layer is clean *before* any actor starts
214
+ persistence_startup=PersistenceStartupConfig(
215
+ mode=PersistenceStartupMode.RECOVER,
216
+ recovery=PersistenceRecoveryConfig(mode=PersistenceRecoveryMode.REPAIR),
217
+ ),
218
+ )
219
+
220
+ await system.start()
221
+ ```
222
+
223
+ - `fail_on_anomaly` → start fails if corruption is detected
224
+ - `recover` → attempt recovery, then require a clean post-scan
225
+ - `ignore` / `scan_only` → don't fail startup
226
+
227
+ ### 3) Spawn actors after the system starts
228
+
229
+ ```python
230
+ from papyra.actor import Actor
231
+
232
+ class Echo(Actor):
233
+ async def receive(self, message):
234
+ return message
235
+
236
+ ref = system.spawn(Echo, name="echo")
237
+ ```
238
+
239
+ ### 4) Shut down cleanly
240
+
241
+ ```python
242
+ await system.aclose()
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Operational CLI
248
+
249
+ ### Health check (Doctor)
250
+
251
+ ```bash
252
+ papyra doctor run
253
+ ```
254
+
255
+ Fail hard if there are anomalies:
256
+
257
+ ```bash
258
+ papyra doctor run --mode fail_on_anomaly
259
+ ```
260
+
261
+ Attempt recovery:
262
+
263
+ ```bash
264
+ papyra doctor run --mode recover --recovery-mode repair
265
+ ```
266
+
267
+ ### Persistence maintenance
268
+
269
+ Scan:
270
+
271
+ ```bash
272
+ papyra persistence scan --path ./papyra.ndjson
273
+ ```
274
+
275
+ Recover:
276
+
277
+ ```bash
278
+ papyra persistence recover --mode repair --path ./papyra.ndjson
279
+ ```
280
+
281
+ Compact:
282
+
283
+ ```bash
284
+ papyra persistence compact --path ./papyra.ndjson
285
+ ```
286
+
287
+ Inspect summary:
288
+
289
+ ```bash
290
+ papyra persistence inspect --path ./papyra.ndjson --show-metrics
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Documentation
296
+
297
+ The full documentation covers:
298
+
299
+ - Core concepts and actor lifecycle observability
300
+ - All persistence backends (JSON, rotation, Redis, memory)
301
+ - Retention and compaction strategies
302
+ - Failure scenarios and recovery playbooks
303
+ - Startup guarantees
304
+ - Metrics + OpenTelemetry integration
305
+ - Extending Papyra with custom backends
papyra-0.1.0/README.md ADDED
@@ -0,0 +1,251 @@
1
+ # Papyra
2
+
3
+ <p align="center">
4
+ <a href="https://papyra.dymmond.com"><img src="https://res.cloudinary.com/dymmond/image/upload/v1768380322/Papyra/logo_wgunlg.png" alt='Papyra'></a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <em>Durable persistence, retention and compaction for actor systems</em>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://github.com/dymmond/papyra/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" target="_blank">
13
+ <img src="https://github.com/dymmond/papyra/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" alt="Test Suite">
14
+ </a>
15
+
16
+ <a href="https://pypi.org/project/papyra" target="_blank">
17
+ <img src="https://img.shields.io/pypi/v/papyra?color=%2334D058&label=pypi%20package" alt="Package version">
18
+ </a>
19
+
20
+ <a href="https://pypi.org/project/papyra" target="_blank">
21
+ <img src="https://img.shields.io/pypi/pyversions/papyra.svg?color=%2334D058" alt="Supported Python versions">
22
+ </a>
23
+ </p>
24
+
25
+ ---
26
+
27
+ **Documentation**: [https://papyra.dymmond.com](https://papyra.dymmond.com) 📚
28
+
29
+ **Source Code**: [https://github.com/dymmond/papyra](https://github.com/dymmond/papyra)
30
+
31
+ **The official supported version is always the latest released**.
32
+
33
+ ---
34
+
35
+ **Durable persistence, retention, recovery, and observability for actor systems.**
36
+
37
+ Papyra is a production-grade persistence layer designed specifically for **actor-based runtimes**.
38
+ It provides **durable system history**, **audits**, **dead-letter tracking**, **retention + compaction**,
39
+ **startup health checks**, **recovery orchestration**, and **operational tooling**.
40
+
41
+ > Papyra is not an actor framework.
42
+ > It's the **persistence and observability backbone** that makes an actor system operationally safe.
43
+
44
+ ---
45
+
46
+ ## Why Papyra?
47
+
48
+ Actor systems are excellent at concurrency and fault isolation, but production operators eventually need:
49
+
50
+ - A durable history of lifecycle events (start/stop/crash/restart)
51
+ - Audit snapshots for “what's running and what's broken?”
52
+ - Dead letters for undeliverable messages
53
+ - Retention to prevent unbounded growth
54
+ - Compaction to physically reclaim disk space
55
+ - Startup checks and deterministic recovery
56
+ - Metrics for observability
57
+ - CLI tools for real-world operations
58
+
59
+ Papyra solves this **explicitly** and safely.
60
+
61
+ ---
62
+
63
+ ## Features
64
+
65
+ ### 🧱 Persistence backends
66
+
67
+ - **JSON NDJSON file** backend (simple, readable, portable)
68
+ - **Rotating files** backend (bounded disk usage)
69
+ - **Redis Streams** backend (production, distributed, consumer-groups)
70
+ - **In-memory** backend (tests, ephemeral)
71
+
72
+ ### ♻️ Retention & compaction
73
+
74
+ - Record-count, age, and size-based retention
75
+ - Explicit **physical compaction / vacuum**
76
+ - Crash-safe atomic rewrite semantics where applicable
77
+
78
+ ### 🩺 Health, startup checks & recovery
79
+
80
+ - Scan for corruption / anomalies
81
+ - Recovery modes: **IGNORE / REPAIR / QUARANTINE**
82
+ - Startup orchestration to guarantee a clean persistence layer before actors start
83
+
84
+ ### 📊 Metrics & integration
85
+
86
+ - Backend metrics (writes, errors, scans, recoveries, compactions)
87
+ - CLI metrics output
88
+ - Optional OpenTelemetry integration
89
+
90
+ ### 🛠️ CLI
91
+
92
+ - `persistence scan | recover | compact | inspect | startup-check`
93
+ - `doctor run`
94
+ - `inspect events | audits | dead-letters | summary`
95
+ - `metrics …`
96
+
97
+ ---
98
+
99
+ ## Installation
100
+
101
+ ```bash
102
+ pip install papyra
103
+ ```
104
+
105
+ Optional extras:
106
+
107
+ ```bash
108
+ pip install papyra[redis]
109
+ ```
110
+
111
+ ---
112
+
113
+ ## ActorSystem + Papyra: the mental model
114
+
115
+ An `ActorSystem` emits **observable facts** while it runs:
116
+
117
+ - **Events**: lifecycle transitions (started, stopped, crashed, restarted)
118
+ - **Audits**: point-in-time health snapshots (counts, registry status, dead letters)
119
+ - **Dead letters**: messages that couldn't be delivered
120
+
121
+ Papyra persists these facts using the configured backend.
122
+
123
+ A key guarantee: **startup checks happen before any actor is allowed to run**.
124
+ If the persistence layer is corrupted and startup mode is strict, `ActorSystem.start()` fails.
125
+
126
+ ---
127
+
128
+ ## Quickstart (with ActorSystem)
129
+
130
+ ### 1) Pick a persistence backend
131
+
132
+ #### JSON file backend
133
+
134
+ ```python
135
+ from papyra.persistence.json import JsonFilePersistence
136
+
137
+ persistence = JsonFilePersistence("./papyra.ndjson")
138
+ ```
139
+
140
+ #### Redis Streams backend
141
+
142
+ ```python
143
+ from papyra.persistence.backends.redis import RedisStreamsConfig, RedisStreamsPersistence
144
+
145
+ persistence = RedisStreamsPersistence(
146
+ RedisStreamsConfig(url="redis://localhost:6379/0", prefix="papyra", system_id="local")
147
+ )
148
+ ```
149
+
150
+ ### 2) Start the ActorSystem with startup checks
151
+
152
+ ```python
153
+ from papyra.system import ActorSystem
154
+ from papyra.persistence.startup import PersistenceStartupConfig, PersistenceStartupMode
155
+ from papyra.persistence.models import PersistenceRecoveryConfig, PersistenceRecoveryMode
156
+
157
+ system = ActorSystem(
158
+ persistence=persistence,
159
+ # Ensure the persistence layer is clean *before* any actor starts
160
+ persistence_startup=PersistenceStartupConfig(
161
+ mode=PersistenceStartupMode.RECOVER,
162
+ recovery=PersistenceRecoveryConfig(mode=PersistenceRecoveryMode.REPAIR),
163
+ ),
164
+ )
165
+
166
+ await system.start()
167
+ ```
168
+
169
+ - `fail_on_anomaly` → start fails if corruption is detected
170
+ - `recover` → attempt recovery, then require a clean post-scan
171
+ - `ignore` / `scan_only` → don't fail startup
172
+
173
+ ### 3) Spawn actors after the system starts
174
+
175
+ ```python
176
+ from papyra.actor import Actor
177
+
178
+ class Echo(Actor):
179
+ async def receive(self, message):
180
+ return message
181
+
182
+ ref = system.spawn(Echo, name="echo")
183
+ ```
184
+
185
+ ### 4) Shut down cleanly
186
+
187
+ ```python
188
+ await system.aclose()
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Operational CLI
194
+
195
+ ### Health check (Doctor)
196
+
197
+ ```bash
198
+ papyra doctor run
199
+ ```
200
+
201
+ Fail hard if there are anomalies:
202
+
203
+ ```bash
204
+ papyra doctor run --mode fail_on_anomaly
205
+ ```
206
+
207
+ Attempt recovery:
208
+
209
+ ```bash
210
+ papyra doctor run --mode recover --recovery-mode repair
211
+ ```
212
+
213
+ ### Persistence maintenance
214
+
215
+ Scan:
216
+
217
+ ```bash
218
+ papyra persistence scan --path ./papyra.ndjson
219
+ ```
220
+
221
+ Recover:
222
+
223
+ ```bash
224
+ papyra persistence recover --mode repair --path ./papyra.ndjson
225
+ ```
226
+
227
+ Compact:
228
+
229
+ ```bash
230
+ papyra persistence compact --path ./papyra.ndjson
231
+ ```
232
+
233
+ Inspect summary:
234
+
235
+ ```bash
236
+ papyra persistence inspect --path ./papyra.ndjson --show-metrics
237
+ ```
238
+
239
+ ---
240
+
241
+ ## Documentation
242
+
243
+ The full documentation covers:
244
+
245
+ - Core concepts and actor lifecycle observability
246
+ - All persistence backends (JSON, rotation, Redis, memory)
247
+ - Retention and compaction strategies
248
+ - Failure scenarios and recovery playbooks
249
+ - Startup guarantees
250
+ - Metrics + OpenTelemetry integration
251
+ - Extending Papyra with custom backends
@@ -0,0 +1,47 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from .monkay import create_monkay
4
+
5
+ __version__ = "0.1.0"
6
+
7
+ if TYPE_CHECKING:
8
+ from ._envelope import DeadLetter
9
+ from .actor import Actor
10
+ from .audit import ActorInfo, AuditReport
11
+ from .conf import settings
12
+ from .conf.global_settings import Settings
13
+ from .context import ActorContext
14
+ from .exceptions import ActorStopped, AskTimeout, MailboxClosed, PapyraError
15
+ from .hooks import FailureInfo, SystemHooks
16
+ from .ref import ActorRef
17
+ from .supervision import Strategy, SupervisionPolicy
18
+ from .supervisor import SupervisorDecision
19
+ from .system import ActorSystem
20
+ from .typing import Receives, ReceivesAny
21
+
22
+
23
+ __all__ = [
24
+ "Actor",
25
+ "ActorContext",
26
+ "ActorRef",
27
+ "ActorSystem",
28
+ "ActorInfo",
29
+ "AuditReport",
30
+ "PapyraError",
31
+ "ActorStopped",
32
+ "AskTimeout",
33
+ "MailboxClosed",
34
+ "Strategy",
35
+ "SupervisionPolicy",
36
+ "SupervisorDecision",
37
+ "DeadLetter",
38
+ "Receives",
39
+ "ReceivesAny",
40
+ "Settings",
41
+ "settings",
42
+ "SystemHooks",
43
+ "FailureInfo",
44
+ ]
45
+
46
+ monkay = create_monkay(globals())
47
+ del create_monkay