Skip to content

Commit 18f1825

Browse files
feat: add runtime server version compatibility check at worker registration
Added automatic server version validation when workers start: **Client (client.py):** - New method: get_cluster_info() fetches server version from GET /api/cluster/info - Returns server version, capabilities, and supported SDK versions **Worker (worker.py):** - _register() now checks server version before registering worker - Validates server major version is 0 (prerelease) or 2+ (stable) - SDK 0.1.x compatible with server 0.x and 2.x - Raises clear error if incompatible: "Server version X is incompatible with sdk-python 0.1.x" - Logs warning and continues if version check fails (non-fatal) **README:** - Added Compatibility section documenting server 0.x and 2.x support - Notes automatic version checking at startup Prevents cryptic protocol errors when SDK paired with incompatible server. Workers now fail fast with actionable version mismatch messages. Fixes #257 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 7008ab5 commit 18f1825

3 files changed

Lines changed: 39 additions & 0 deletions

File tree

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ Full documentation is available at [durable-workflow.github.io/docs/2.0/sdks/pyt
7575
- Python ≥ 3.10
7676
- A running [Durable Workflow server](https://github.com/durable-workflow/server)
7777

78+
## Compatibility
79+
80+
SDK version 0.1.x is compatible with:
81+
- **Server 0.x** (development/prerelease versions 0.1.0 through 0.1.9+)
82+
- **Server 2.x** (stable release versions 2.0.0+)
83+
84+
The worker automatically checks server version at startup and raises a clear error if incompatible.
85+
7886
## Development
7987

8088
```bash

src/durable_workflow/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ async def _do_request() -> httpx.Response:
299299
return None
300300
return resp.json()
301301

302+
async def get_cluster_info(self) -> dict[str, Any]:
303+
"""Fetch server version and capabilities from /api/cluster/info."""
304+
return await self._request("GET", "/cluster/info", worker=False, context="get_cluster_info")
305+
302306
def get_workflow_handle(
303307
self, workflow_id: str, *, run_id: str | None = None, workflow_type: str = ""
304308
) -> WorkflowHandle:

src/durable_workflow/worker.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,33 @@ def __init__(
5252
self._in_flight: set[asyncio.Task[Any]] = set()
5353

5454
async def _register(self) -> None:
55+
# Check server version compatibility
56+
try:
57+
info = await self.client.get_cluster_info()
58+
server_version = info.get("version", "unknown")
59+
60+
# Parse major version (e.g., "0.1.9" -> 0, "2.0.0" -> 2)
61+
try:
62+
major = int(server_version.split(".")[0])
63+
except (ValueError, IndexError):
64+
log.warning("unable to parse server version %r; skipping compatibility check", server_version)
65+
major = None
66+
67+
# Require server major version 0 or 2+ (0.x is pre-release, 2.x is stable)
68+
# SDK 0.1.x is compatible with server 0.1.x and 2.x
69+
if major is not None and major not in (0, 2):
70+
raise RuntimeError(
71+
f"Server version {server_version} is incompatible with sdk-python 0.1.x "
72+
f"(requires server 0.x or 2.x). "
73+
f"Upgrade the server or use a compatible SDK version."
74+
)
75+
76+
log.debug("server version %s is compatible", server_version)
77+
except Exception as e:
78+
if isinstance(e, RuntimeError) and "incompatible" in str(e):
79+
raise
80+
log.warning("failed to check server version compatibility: %s", e)
81+
5582
await self.client.register_worker(
5683
worker_id=self.worker_id,
5784
task_queue=self.task_queue,

0 commit comments

Comments
 (0)