hatchet-sdk 0.42.5__py3-none-any.whl → 0.43.0__py3-none-any.whl

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.

Potentially problematic release.


This version of hatchet-sdk might be problematic. Click here for more details.

hatchet_sdk/loader.py CHANGED
@@ -43,6 +43,8 @@ class ClientConfig:
43
43
  otel_service_name: str | None = None,
44
44
  otel_exporter_oltp_headers: dict[str, str] | None = None,
45
45
  otel_exporter_oltp_protocol: str | None = None,
46
+ worker_healthcheck_port: int | None = None,
47
+ worker_healthcheck_enabled: bool | None = None,
46
48
  ):
47
49
  self.tenant_id = tenant_id
48
50
  self.tls_config = tls_config
@@ -57,6 +59,8 @@ class ClientConfig:
57
59
  self.otel_service_name = otel_service_name
58
60
  self.otel_exporter_oltp_headers = otel_exporter_oltp_headers
59
61
  self.otel_exporter_oltp_protocol = otel_exporter_oltp_protocol
62
+ self.worker_healthcheck_port = worker_healthcheck_port
63
+ self.worker_healthcheck_enabled = worker_healthcheck_enabled
60
64
 
61
65
  if not self.logInterceptor:
62
66
  self.logInterceptor = getLogger()
@@ -163,6 +167,23 @@ class ConfigLoader:
163
167
  "otel_exporter_oltp_protocol", "HATCHET_CLIENT_OTEL_EXPORTER_OTLP_PROTOCOL"
164
168
  )
165
169
 
170
+ worker_healthcheck_port = int(
171
+ get_config_value(
172
+ "worker_healthcheck_port", "HATCHET_CLIENT_WORKER_HEALTHCHECK_PORT"
173
+ )
174
+ or 8001
175
+ )
176
+
177
+ worker_healthcheck_enabled = (
178
+ str(
179
+ get_config_value(
180
+ "worker_healthcheck_port",
181
+ "HATCHET_CLIENT_WORKER_HEALTHCHECK_ENABLED",
182
+ )
183
+ )
184
+ == "True"
185
+ )
186
+
166
187
  return ClientConfig(
167
188
  tenant_id=tenant_id,
168
189
  tls_config=tls_config,
@@ -178,6 +199,8 @@ class ConfigLoader:
178
199
  otel_service_name=otel_service_name,
179
200
  otel_exporter_oltp_headers=otel_exporter_oltp_headers,
180
201
  otel_exporter_oltp_protocol=otel_exporter_oltp_protocol,
202
+ worker_healthcheck_port=worker_healthcheck_port,
203
+ worker_healthcheck_enabled=worker_healthcheck_enabled,
181
204
  )
182
205
 
183
206
  def _load_tls_config(self, tls_data: Dict, host_port) -> ClientTLSConfig:
@@ -12,7 +12,10 @@ from multiprocessing.process import BaseProcess
12
12
  from types import FrameType
13
13
  from typing import Any, Callable, TypeVar, get_type_hints
14
14
 
15
- from pydantic import BaseModel
15
+ from aiohttp import web
16
+ from aiohttp.web_request import Request
17
+ from aiohttp.web_response import Response
18
+ from prometheus_client import CONTENT_TYPE_LATEST, Gauge, generate_latest
16
19
 
17
20
  from hatchet_sdk import Context
18
21
  from hatchet_sdk.client import Client, new_client_raw
@@ -88,6 +91,10 @@ class Worker:
88
91
 
89
92
  self._setup_signal_handlers()
90
93
 
94
+ self.worker_status_gauge = Gauge(
95
+ "hatchet_worker_status", "Current status of the Hatchet worker"
96
+ )
97
+
91
98
  def register_function(self, action: str, func: Callable[[Context], Any]) -> None:
92
99
  self.action_registry[action] = func
93
100
 
@@ -155,6 +162,39 @@ class Worker:
155
162
  created_loop = True
156
163
  return created_loop
157
164
 
165
+ async def health_check_handler(self, request: Request) -> Response:
166
+ status = self.status()
167
+
168
+ return web.json_response({"status": status.name})
169
+
170
+ async def metrics_handler(self, request: Request) -> Response:
171
+ self.worker_status_gauge.set(1 if self.status() == WorkerStatus.HEALTHY else 0)
172
+
173
+ return web.Response(body=generate_latest(), content_type="text/plain")
174
+
175
+ async def start_health_server(self) -> None:
176
+ port = self.config.worker_healthcheck_port or 8001
177
+
178
+ app = web.Application()
179
+ app.add_routes(
180
+ [
181
+ web.get("/health", self.health_check_handler),
182
+ web.get("/metrics", self.metrics_handler),
183
+ ]
184
+ )
185
+
186
+ runner = web.AppRunner(app)
187
+
188
+ try:
189
+ await runner.setup()
190
+ await web.TCPSite(runner, "0.0.0.0", port).start()
191
+ except Exception as e:
192
+ logger.error("failed to start healthcheck server")
193
+ logger.error(str(e))
194
+ return
195
+
196
+ logger.info(f"healthcheck server running on port {port}")
197
+
158
198
  def start(
159
199
  self, options: WorkerStartOptions = WorkerStartOptions()
160
200
  ) -> Future[asyncio.Task[Any] | None]:
@@ -196,6 +236,9 @@ class Worker:
196
236
  if not _from_start:
197
237
  self.setup_loop(options.loop)
198
238
 
239
+ if self.config.worker_healthcheck_enabled:
240
+ await self.start_health_server()
241
+
199
242
  self.action_listener_process = self._start_listener()
200
243
 
201
244
  self.action_runner = self._run_action_runner()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hatchet-sdk
3
- Version: 0.42.5
3
+ Version: 0.43.0
4
4
  Summary:
5
5
  Author: Alexander Belanger
6
6
  Author-email: alexander@hatchet.run
@@ -23,6 +23,7 @@ Requires-Dist: opentelemetry-exporter-otlp (>=1.27.0,<2.0.0)
23
23
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0)
24
24
  Requires-Dist: opentelemetry-instrumentation (>=0.48b0,<0.49)
25
25
  Requires-Dist: opentelemetry-sdk (>=1.27.0,<2.0.0)
26
+ Requires-Dist: prometheus-client (>=0.21.1,<0.22.0)
26
27
  Requires-Dist: protobuf (>=5.29.1,<6.0.0)
27
28
  Requires-Dist: pydantic (>=2.6.3,<3.0.0)
28
29
  Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
@@ -205,7 +205,7 @@ hatchet_sdk/features/cron.py,sha256=4lKMH0MqiN8cHJk2jhF0Ueqs6z5ozwJzlOeSeaWqvO0,
205
205
  hatchet_sdk/features/scheduled.py,sha256=YhEbNWl8dWOH61rXVjAyu8iG1BZqpSkD4kgaxkKIHgY,9504
206
206
  hatchet_sdk/hatchet.py,sha256=UpCDv3q-Mrbwi7tFHS2FonBwwXlbs5kRFfCfx4DJVeI,10027
207
207
  hatchet_sdk/labels.py,sha256=Axfp1yUNowzE9mL8AQA1ADqwOaNmq3QP_45wb1Ed1aI,272
208
- hatchet_sdk/loader.py,sha256=dGs6Tt8wdEgHeCBesbbQsP6ZYiARBvoqwIdXIO1P5Os,7913
208
+ hatchet_sdk/loader.py,sha256=ddwQ7BAWYsJ9LEsNxajCkv78hRLUMftVG0vdg5V09iQ,8746
209
209
  hatchet_sdk/logger.py,sha256=5uOr52T4mImSQm1QvWT8HvZFK5WfPNh3Y1cBQZRFgUQ,333
210
210
  hatchet_sdk/metadata.py,sha256=M_Cb-CXRKitzVMQHeaHUtbY28ET__fAbyGX1YKaeN4I,80
211
211
  hatchet_sdk/rate_limit.py,sha256=IIzpe65i-518t9kQcZVEykDQ2VY8sOw2F7qlQ4wlAjw,4421
@@ -226,10 +226,10 @@ hatchet_sdk/worker/runner/run_loop_manager.py,sha256=nV7fhNxJKCcrBm0ci118aszF_7A
226
226
  hatchet_sdk/worker/runner/runner.py,sha256=uNHPViiQvtwvX4uJ9TqcbFPonJnhhoEM3WNOWEKyop0,18517
227
227
  hatchet_sdk/worker/runner/utils/capture_logs.py,sha256=s_BGxeykelVbusx6u31EPx3vv9c2BHkuBnYcaLW680E,2381
228
228
  hatchet_sdk/worker/runner/utils/error_with_traceback.py,sha256=Iih_s8JNqrinXETFJ3ZS88EhaTekfM6m5fqIP7QWoIM,181
229
- hatchet_sdk/worker/worker.py,sha256=R4UEf_1e7qe1LrXS8-0fjfriwcSb3W_38RUR6pOxBCo,11547
229
+ hatchet_sdk/worker/worker.py,sha256=7UPm3qTzNYSSm9QTNX6zBBMJqVA6nKFeCbAdqLLjUBs,13007
230
230
  hatchet_sdk/workflow.py,sha256=XRj5jcCQSvPQMXxBipf-ZlARua2E8Z9igRzGcQ5alkI,9375
231
231
  hatchet_sdk/workflow_run.py,sha256=BwK5cefvXXvyQ1Ednj_7LeejMwQJqWnvUC_FTBmJNxk,1805
232
- hatchet_sdk-0.42.5.dist-info/METADATA,sha256=BztALlvM5Evu2RNQwVaMfnWJR6WqsKwgxCE3HCb4oZg,1514
233
- hatchet_sdk-0.42.5.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
234
- hatchet_sdk-0.42.5.dist-info/entry_points.txt,sha256=LTtQRABmSGYOxRI68cUVEz5dp9Qb57eqXGic9lU8RMo,1023
235
- hatchet_sdk-0.42.5.dist-info/RECORD,,
232
+ hatchet_sdk-0.43.0.dist-info/METADATA,sha256=KaGqauwS0IcnkdmMDQLHvw8AMIdoXQ1iP_1w4mNnEAI,1566
233
+ hatchet_sdk-0.43.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
234
+ hatchet_sdk-0.43.0.dist-info/entry_points.txt,sha256=LTtQRABmSGYOxRI68cUVEz5dp9Qb57eqXGic9lU8RMo,1023
235
+ hatchet_sdk-0.43.0.dist-info/RECORD,,