edgesync 0.3.2__tar.gz → 0.3.3__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.
- {edgesync-0.3.2 → edgesync-0.3.3}/CHANGELOG.md +9 -1
- {edgesync-0.3.2 → edgesync-0.3.3}/PKG-INFO +21 -23
- {edgesync-0.3.2 → edgesync-0.3.3}/README.md +19 -20
- edgesync-0.3.3/VERSION +1 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/docs/getting-started.md +19 -20
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/transports/mqtt.py +2 -9
- {edgesync-0.3.2 → edgesync-0.3.3}/pyproject.toml +1 -3
- {edgesync-0.3.2 → edgesync-0.3.3}/uv.lock +2 -7
- edgesync-0.3.2/VERSION +0 -1
- {edgesync-0.3.2 → edgesync-0.3.3}/.github/workflows/ci.yml +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/.github/workflows/release.yml +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/.gitignore +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/CONTRIBUTING.md +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/LICENSE +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/SECURITY.md +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/docs/integrations.md +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/docs/reliability.md +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/docs/storage.md +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/client.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/config.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/exceptions.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/logging.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/models/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/models/delivery.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/models/message.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/models/receipt.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/models/stats.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/py.typed +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/queue/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/queue/manager.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/retry/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/retry/backoff.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/retry/policy.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/storage/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/storage/base.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/storage/migrations.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/storage/sqlite.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/transports/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/transports/base.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/transports/http.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/transports/registry.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/utils/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/utils/clock.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/utils/ids.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/worker/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/worker/lifecycle.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/worker/scheduler.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/edgesync/worker/sync_worker.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/conftest.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/fixtures/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/fixtures/factories.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/fixtures/fake_transport.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/integration/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/integration/test_client.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/integration/test_http_transport.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/integration/test_mqtt_transport.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/integration/test_sqlite_storage.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/integration/test_worker.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/reliability/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/reliability/test_reliability.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/unit/__init__.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/unit/test_backoff.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/unit/test_config.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/unit/test_models.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/unit/test_queue_manager.py +0 -0
- {edgesync-0.3.2 → edgesync-0.3.3}/tests/unit/test_retry_policy.py +0 -0
|
@@ -7,6 +7,13 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.3] - 2026-09-13
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- `aiomqtt` is now a required dependency instead of an optional `mqtt` extra, so
|
|
15
|
+
`pip install edgesync` alone is enough to use `MQTTTransport`.
|
|
16
|
+
|
|
10
17
|
## [0.3.2] - 2026-08-24
|
|
11
18
|
|
|
12
19
|
### Added
|
|
@@ -97,7 +104,8 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
97
104
|
- Crash and restart recovery via expired-lease sweeps, safe across concurrent workers and
|
|
98
105
|
processes sharing the same database file.
|
|
99
106
|
|
|
100
|
-
[Unreleased]: https://github.com/adhuldas/EdgeSync/compare/v0.3.
|
|
107
|
+
[Unreleased]: https://github.com/adhuldas/EdgeSync/compare/v0.3.3...HEAD
|
|
108
|
+
[0.3.3]: https://github.com/adhuldas/EdgeSync/compare/v0.3.2...v0.3.3
|
|
101
109
|
[0.3.2]: https://github.com/adhuldas/EdgeSync/compare/v0.3.1...v0.3.2
|
|
102
110
|
[0.3.1]: https://github.com/adhuldas/EdgeSync/compare/v0.3.0...v0.3.1
|
|
103
111
|
[0.3.0]: https://github.com/adhuldas/EdgeSync/compare/v0.2.1...v0.3.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: edgesync
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Reliable data delivery for unreliable networks.
|
|
5
5
|
Project-URL: Homepage, https://github.com/adhuldas/EdgeSync
|
|
6
6
|
Project-URL: Repository, https://github.com/adhuldas/EdgeSync
|
|
@@ -25,10 +25,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
25
25
|
Classifier: Topic :: System :: Distributed Computing
|
|
26
26
|
Classifier: Typing :: Typed
|
|
27
27
|
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: aiomqtt<3,>=2.5
|
|
28
29
|
Requires-Dist: aiosqlite>=0.20
|
|
29
30
|
Requires-Dist: httpx>=0.27
|
|
30
|
-
Provides-Extra: mqtt
|
|
31
|
-
Requires-Dist: aiomqtt<3,>=2.5; extra == 'mqtt'
|
|
32
31
|
Description-Content-Type: text/markdown
|
|
33
32
|
|
|
34
33
|
# EdgeSync
|
|
@@ -96,33 +95,32 @@ caller needing to stay connected or wait for the network.
|
|
|
96
95
|
|
|
97
96
|
## MQTT
|
|
98
97
|
|
|
99
|
-
Install the optional extra first:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
pip install edgesync[mqtt]
|
|
103
|
-
```
|
|
104
|
-
|
|
105
98
|
Publishing to MQTT instead of HTTP is the same pattern with a different transport:
|
|
106
99
|
|
|
107
100
|
```python
|
|
101
|
+
import asyncio
|
|
108
102
|
from edgesync import EdgeSync
|
|
109
103
|
from edgesync.transports.mqtt import MQTTTransport
|
|
110
104
|
|
|
111
|
-
sync = EdgeSync(
|
|
112
|
-
database="edgesync.db",
|
|
113
|
-
destinations={
|
|
114
|
-
"telemetry": MQTTTransport(
|
|
115
|
-
"broker.example.com",
|
|
116
|
-
"devices/device-001/telemetry",
|
|
117
|
-
qos=1,
|
|
118
|
-
username="device-001",
|
|
119
|
-
password="...",
|
|
120
|
-
),
|
|
121
|
-
},
|
|
122
|
-
default_destination="telemetry",
|
|
123
|
-
)
|
|
124
105
|
|
|
125
|
-
|
|
106
|
+
async def main():
|
|
107
|
+
async with EdgeSync(
|
|
108
|
+
database="edgesync.db",
|
|
109
|
+
destinations={
|
|
110
|
+
"telemetry": MQTTTransport(
|
|
111
|
+
"broker.example.com",
|
|
112
|
+
"devices/device-001/telemetry",
|
|
113
|
+
qos=1,
|
|
114
|
+
username="device-001",
|
|
115
|
+
password="...",
|
|
116
|
+
),
|
|
117
|
+
},
|
|
118
|
+
default_destination="telemetry",
|
|
119
|
+
) as sync:
|
|
120
|
+
await sync.publish({"temperature": 28.5})
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
asyncio.run(main())
|
|
126
124
|
```
|
|
127
125
|
|
|
128
126
|
`MQTTTransport` only accepts QoS 1 or 2 — QoS 0 publishes are never acknowledged by the
|
|
@@ -63,33 +63,32 @@ caller needing to stay connected or wait for the network.
|
|
|
63
63
|
|
|
64
64
|
## MQTT
|
|
65
65
|
|
|
66
|
-
Install the optional extra first:
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
pip install edgesync[mqtt]
|
|
70
|
-
```
|
|
71
|
-
|
|
72
66
|
Publishing to MQTT instead of HTTP is the same pattern with a different transport:
|
|
73
67
|
|
|
74
68
|
```python
|
|
69
|
+
import asyncio
|
|
75
70
|
from edgesync import EdgeSync
|
|
76
71
|
from edgesync.transports.mqtt import MQTTTransport
|
|
77
72
|
|
|
78
|
-
sync = EdgeSync(
|
|
79
|
-
database="edgesync.db",
|
|
80
|
-
destinations={
|
|
81
|
-
"telemetry": MQTTTransport(
|
|
82
|
-
"broker.example.com",
|
|
83
|
-
"devices/device-001/telemetry",
|
|
84
|
-
qos=1,
|
|
85
|
-
username="device-001",
|
|
86
|
-
password="...",
|
|
87
|
-
),
|
|
88
|
-
},
|
|
89
|
-
default_destination="telemetry",
|
|
90
|
-
)
|
|
91
73
|
|
|
92
|
-
|
|
74
|
+
async def main():
|
|
75
|
+
async with EdgeSync(
|
|
76
|
+
database="edgesync.db",
|
|
77
|
+
destinations={
|
|
78
|
+
"telemetry": MQTTTransport(
|
|
79
|
+
"broker.example.com",
|
|
80
|
+
"devices/device-001/telemetry",
|
|
81
|
+
qos=1,
|
|
82
|
+
username="device-001",
|
|
83
|
+
password="...",
|
|
84
|
+
),
|
|
85
|
+
},
|
|
86
|
+
default_destination="telemetry",
|
|
87
|
+
) as sync:
|
|
88
|
+
await sync.publish({"temperature": 28.5})
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
asyncio.run(main())
|
|
93
92
|
```
|
|
94
93
|
|
|
95
94
|
`MQTTTransport` only accepts QoS 1 or 2 — QoS 0 publishes are never acknowledged by the
|
edgesync-0.3.3/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.3.3
|
|
@@ -126,31 +126,30 @@ than HTTP.
|
|
|
126
126
|
|
|
127
127
|
## MQTT
|
|
128
128
|
|
|
129
|
-
Install the optional extra first:
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
pip install edgesync[mqtt]
|
|
133
|
-
```
|
|
134
|
-
|
|
135
129
|
```python
|
|
130
|
+
import asyncio
|
|
136
131
|
from edgesync import EdgeSync
|
|
137
132
|
from edgesync.transports.mqtt import MQTTTransport
|
|
138
133
|
|
|
139
|
-
sync = EdgeSync(
|
|
140
|
-
database="edgesync.db",
|
|
141
|
-
destinations={
|
|
142
|
-
"telemetry": MQTTTransport(
|
|
143
|
-
"broker.example.com",
|
|
144
|
-
"devices/device-001/telemetry",
|
|
145
|
-
qos=1,
|
|
146
|
-
username="device-001",
|
|
147
|
-
password="...",
|
|
148
|
-
),
|
|
149
|
-
},
|
|
150
|
-
default_destination="telemetry",
|
|
151
|
-
)
|
|
152
134
|
|
|
153
|
-
|
|
135
|
+
async def main():
|
|
136
|
+
async with EdgeSync(
|
|
137
|
+
database="edgesync.db",
|
|
138
|
+
destinations={
|
|
139
|
+
"telemetry": MQTTTransport(
|
|
140
|
+
"broker.example.com",
|
|
141
|
+
"devices/device-001/telemetry",
|
|
142
|
+
qos=1,
|
|
143
|
+
username="device-001",
|
|
144
|
+
password="...",
|
|
145
|
+
),
|
|
146
|
+
},
|
|
147
|
+
default_destination="telemetry",
|
|
148
|
+
) as sync:
|
|
149
|
+
await sync.publish({"temperature": 28.5})
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
asyncio.run(main())
|
|
154
153
|
```
|
|
155
154
|
|
|
156
155
|
`MQTTTransport` only accepts QoS 1 or 2 — QoS 0 publishes are never acknowledged by the
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""MQTT transport backed by ``aiomqtt``.
|
|
2
2
|
|
|
3
|
-
Requires the optional ``aiomqtt`` dependency: ``pip install edgesync[mqtt]``.
|
|
4
|
-
|
|
5
3
|
Unlike :class:`~edgesync.transports.http.HTTPTransport`, MQTT is a stateful,
|
|
6
4
|
persistent connection rather than a per-request protocol, which shapes two
|
|
7
5
|
design decisions here:
|
|
@@ -22,18 +20,13 @@ from __future__ import annotations
|
|
|
22
20
|
import contextlib
|
|
23
21
|
import json
|
|
24
22
|
|
|
23
|
+
import aiomqtt
|
|
24
|
+
|
|
25
25
|
from edgesync.logging import logger
|
|
26
26
|
from edgesync.models.delivery import DeliveryResult
|
|
27
27
|
from edgesync.models.message import Message
|
|
28
28
|
from edgesync.transports.base import Transport
|
|
29
29
|
|
|
30
|
-
try:
|
|
31
|
-
import aiomqtt
|
|
32
|
-
except ImportError as exc: # pragma: no cover - exercised only without the extra installed
|
|
33
|
-
raise ImportError(
|
|
34
|
-
"MQTTTransport requires the 'aiomqtt' package. Install it with: pip install edgesync[mqtt]"
|
|
35
|
-
) from exc
|
|
36
|
-
|
|
37
30
|
|
|
38
31
|
class MQTTTransport(Transport):
|
|
39
32
|
"""Publish messages as JSON payloads to a fixed MQTT topic.
|
|
@@ -23,11 +23,9 @@ classifiers = [
|
|
|
23
23
|
dependencies = [
|
|
24
24
|
"httpx>=0.27",
|
|
25
25
|
"aiosqlite>=0.20",
|
|
26
|
+
"aiomqtt>=2.5,<3",
|
|
26
27
|
]
|
|
27
28
|
|
|
28
|
-
[project.optional-dependencies]
|
|
29
|
-
mqtt = ["aiomqtt>=2.5,<3"]
|
|
30
|
-
|
|
31
29
|
[project.urls]
|
|
32
30
|
Homepage = "https://github.com/adhuldas/EdgeSync"
|
|
33
31
|
Repository = "https://github.com/adhuldas/EdgeSync"
|
|
@@ -270,15 +270,11 @@ toml = [
|
|
|
270
270
|
name = "edgesync"
|
|
271
271
|
source = { editable = "." }
|
|
272
272
|
dependencies = [
|
|
273
|
+
{ name = "aiomqtt" },
|
|
273
274
|
{ name = "aiosqlite" },
|
|
274
275
|
{ name = "httpx" },
|
|
275
276
|
]
|
|
276
277
|
|
|
277
|
-
[package.optional-dependencies]
|
|
278
|
-
mqtt = [
|
|
279
|
-
{ name = "aiomqtt" },
|
|
280
|
-
]
|
|
281
|
-
|
|
282
278
|
[package.dev-dependencies]
|
|
283
279
|
dev = [
|
|
284
280
|
{ name = "mypy" },
|
|
@@ -291,11 +287,10 @@ dev = [
|
|
|
291
287
|
|
|
292
288
|
[package.metadata]
|
|
293
289
|
requires-dist = [
|
|
294
|
-
{ name = "aiomqtt",
|
|
290
|
+
{ name = "aiomqtt", specifier = ">=2.5,<3" },
|
|
295
291
|
{ name = "aiosqlite", specifier = ">=0.20" },
|
|
296
292
|
{ name = "httpx", specifier = ">=0.27" },
|
|
297
293
|
]
|
|
298
|
-
provides-extras = ["mqtt"]
|
|
299
294
|
|
|
300
295
|
[package.metadata.requires-dev]
|
|
301
296
|
dev = [
|
edgesync-0.3.2/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.3.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|