dominus-sdk-python 2.1.2__tar.gz → 2.1.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.
Files changed (36) hide show
  1. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/PKG-INFO +1 -1
  2. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/helpers/core.py +77 -23
  3. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus_sdk_python.egg-info/PKG-INFO +1 -1
  4. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/pyproject.toml +1 -1
  5. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/README.md +0 -0
  6. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/__init__.py +0 -0
  7. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/config/__init__.py +0 -0
  8. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/config/endpoints.py +0 -0
  9. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/errors.py +0 -0
  10. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/helpers/__init__.py +0 -0
  11. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/helpers/auth.py +0 -0
  12. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/helpers/cache.py +0 -0
  13. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/helpers/crypto.py +0 -0
  14. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/__init__.py +0 -0
  15. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/_deprecated_crossover.py +0 -0
  16. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/_deprecated_sql.py +0 -0
  17. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/auth.py +0 -0
  18. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/courier.py +0 -0
  19. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/db.py +0 -0
  20. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/ddl.py +0 -0
  21. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/files.py +0 -0
  22. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/health.py +0 -0
  23. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/logs.py +0 -0
  24. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/open.py +0 -0
  25. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/portal.py +0 -0
  26. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/redis.py +0 -0
  27. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/namespaces/secrets.py +0 -0
  28. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/services/__init__.py +0 -0
  29. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/services/_deprecated_architect.py +0 -0
  30. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/services/_deprecated_sovereign.py +0 -0
  31. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus/start.py +0 -0
  32. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus_sdk_python.egg-info/SOURCES.txt +0 -0
  33. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
  34. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus_sdk_python.egg-info/requires.txt +0 -0
  35. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/dominus_sdk_python.egg-info/top_level.txt +0 -0
  36. {dominus_sdk_python-2.1.2 → dominus_sdk_python-2.1.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dominus-sdk-python
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Python SDK for the Dominus Orchestrator Platform
5
5
  Author-email: CareBridge Systems <dev@carebridge.io>
6
6
  License: Proprietary
@@ -64,6 +64,7 @@ async def _get_service_jwt(psk_token: str, base_url: str) -> str:
64
64
  Get service JWT by calling /api/warden/mint with PSK.
65
65
 
66
66
  Uses circuit breaker to prevent retry storms during service outages.
67
+ Retries on 401/5xx with exponential backoff (orchestrator cold start handling).
67
68
 
68
69
  Args:
69
70
  psk_token: PSK token (DOMINUS_TOKEN)
@@ -73,7 +74,7 @@ async def _get_service_jwt(psk_token: str, base_url: str) -> str:
73
74
  JWT token string
74
75
 
75
76
  Raises:
76
- RuntimeError: If circuit is open or auth fails
77
+ RuntimeError: If circuit is open or auth fails after retries
77
78
  """
78
79
  # Circuit breaker check
79
80
  if not sovereign_circuit_breaker.can_execute():
@@ -94,32 +95,85 @@ async def _get_service_jwt(psk_token: str, base_url: str) -> str:
94
95
  body_json = {"method": "auth.self", "params": {}}
95
96
  body_b64 = _b64_encode(body_json)
96
97
 
97
- try:
98
- async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=30.0) as client:
99
- response = await client.post("/api/warden/mint", content=body_b64)
100
- response.raise_for_status()
98
+ # Retry loop for JWT minting (handles orchestrator cold start)
99
+ JWT_MINT_RETRIES = 3
100
+ last_error = None
101
101
 
102
- # Decode base64 response
103
- result = _b64_decode(response.text)
102
+ for attempt in range(JWT_MINT_RETRIES):
103
+ try:
104
+ async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=30.0) as client:
105
+ response = await client.post("/api/warden/mint", content=body_b64)
106
+
107
+ # Check for retryable status codes before raise_for_status
108
+ if response.status_code == 401 or response.status_code >= 500:
109
+ if attempt < JWT_MINT_RETRIES - 1:
110
+ delay = exponential_backoff_with_jitter(attempt, base_delay=2.0, max_delay=10.0)
111
+ print(
112
+ f"[Dominus] JWT mint returned {response.status_code}, "
113
+ f"retrying in {delay:.1f}s (attempt {attempt + 1}/{JWT_MINT_RETRIES})"
114
+ )
115
+ await asyncio.sleep(delay)
116
+ continue
117
+
118
+ response.raise_for_status()
119
+
120
+ # Decode base64 response
121
+ result = _b64_decode(response.text)
104
122
 
105
- if not result.get("success"):
106
- error_msg = result.get("error", "Unknown auth error")
107
- sovereign_circuit_breaker.record_failure()
108
- raise RuntimeError(f"Auth error: {error_msg}")
123
+ if not result.get("success"):
124
+ error_msg = result.get("error", "Unknown auth error")
125
+ sovereign_circuit_breaker.record_failure()
126
+ raise RuntimeError(f"Auth error: {error_msg}")
127
+
128
+ data = result.get("data", {})
129
+ jwt = data.get("access_token") or data.get("token")
130
+ if not jwt:
131
+ sovereign_circuit_breaker.record_failure()
132
+ raise RuntimeError("No JWT token in auth response")
133
+
134
+ # Success - record it
135
+ sovereign_circuit_breaker.record_success()
136
+ return jwt
137
+
138
+ except httpx.TimeoutException as e:
139
+ last_error = e
140
+ if attempt < JWT_MINT_RETRIES - 1:
141
+ delay = exponential_backoff_with_jitter(attempt, base_delay=2.0, max_delay=10.0)
142
+ print(
143
+ f"[Dominus] JWT mint timed out, "
144
+ f"retrying in {delay:.1f}s (attempt {attempt + 1}/{JWT_MINT_RETRIES})"
145
+ )
146
+ await asyncio.sleep(delay)
147
+ continue
148
+ sovereign_circuit_breaker.record_failure()
149
+ raise RuntimeError(f"Failed to get JWT: {e}") from e
150
+
151
+ except httpx.NetworkError as e:
152
+ last_error = e
153
+ if attempt < JWT_MINT_RETRIES - 1:
154
+ delay = exponential_backoff_with_jitter(attempt, base_delay=2.0, max_delay=10.0)
155
+ print(
156
+ f"[Dominus] JWT mint network error ({e}), "
157
+ f"retrying in {delay:.1f}s (attempt {attempt + 1}/{JWT_MINT_RETRIES})"
158
+ )
159
+ await asyncio.sleep(delay)
160
+ continue
161
+ sovereign_circuit_breaker.record_failure()
162
+ raise RuntimeError(f"Failed to get JWT: {e}") from e
109
163
 
110
- data = result.get("data", {})
111
- jwt = data.get("access_token") or data.get("token")
112
- if not jwt:
164
+ except httpx.HTTPStatusError as e:
165
+ last_error = e
166
+ # 4xx errors (except 401 which is retried above) should not be retried
167
+ if 400 <= e.response.status_code < 500 and e.response.status_code != 401:
113
168
  sovereign_circuit_breaker.record_failure()
114
- raise RuntimeError("No JWT token in auth response")
115
-
116
- # Success - record it
117
- sovereign_circuit_breaker.record_success()
118
- return jwt
119
-
120
- except (httpx.TimeoutException, httpx.NetworkError, httpx.HTTPStatusError) as e:
121
- sovereign_circuit_breaker.record_failure()
122
- raise RuntimeError(f"Failed to get JWT: {e}") from e
169
+ raise RuntimeError(f"Failed to get JWT: {e}") from e
170
+ # For other errors, we've already handled retries in the status check above
171
+ sovereign_circuit_breaker.record_failure()
172
+ raise RuntimeError(f"Failed to get JWT: {e}") from e
173
+
174
+ # Should not reach here, but just in case
175
+ sovereign_circuit_breaker.record_failure()
176
+ raise RuntimeError(f"Failed to get JWT after {JWT_MINT_RETRIES} retries: {last_error}")
123
177
 
124
178
 
125
179
  def _get_architect_url(psk_token: str = None, sovereign_url: str = None, environment: str = None) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dominus-sdk-python
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Python SDK for the Dominus Orchestrator Platform
5
5
  Author-email: CareBridge Systems <dev@carebridge.io>
6
6
  License: Proprietary
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dominus-sdk-python"
7
- version = "2.1.2"
7
+ version = "2.1.3"
8
8
  description = "Python SDK for the Dominus Orchestrator Platform"
9
9
  readme = "README.md"
10
10
  license = {text = "Proprietary"}