nebu 0.1.88__py3-none-any.whl → 0.1.93__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.
- nebu/cache.py +15 -11
- nebu/containers/container.py +19 -13
- nebu/data.py +112 -92
- nebu/logging.py +33 -0
- nebu/namespaces/namespace.py +15 -8
- nebu/processors/consumer.py +244 -192
- nebu/processors/consumer_process_worker.py +179 -96
- nebu/processors/decorate.py +245 -219
- nebu/processors/processor.py +47 -32
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/METADATA +2 -1
- nebu-0.1.93.dist-info/RECORD +28 -0
- nebu/containers/decorator.py +0 -93
- nebu/containers/server.py +0 -70
- nebu/processors/remote.py +0 -47
- nebu-0.1.88.dist-info/RECORD +0 -30
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/WHEEL +0 -0
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/licenses/LICENSE +0 -0
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/top_level.txt +0 -0
@@ -15,6 +15,7 @@ import redis
|
|
15
15
|
import socks
|
16
16
|
|
17
17
|
from nebu.errors import RetriableError
|
18
|
+
from nebu.logging import logger # Import the logger
|
18
19
|
|
19
20
|
# from redis import ConnectionError, ResponseError # Removed unused imports
|
20
21
|
|
@@ -57,16 +58,20 @@ def load_user_code(
|
|
57
58
|
loaded_module = None
|
58
59
|
exec_namespace: Dict[str, Any] = {} # Use a local namespace for this load attempt
|
59
60
|
|
60
|
-
|
61
|
+
logger.info(
|
62
|
+
f"[Worker Code Loader] Attempting to load module: '{module_path}'"
|
63
|
+
) # Changed from print
|
61
64
|
os.environ[_NEBU_INSIDE_CONSUMER_ENV_VAR] = "1" # Set guard *before* import
|
62
|
-
print
|
65
|
+
logger.debug( # Changed from print to debug
|
63
66
|
f"[Worker Code Loader] Set environment variable {_NEBU_INSIDE_CONSUMER_ENV_VAR}=1"
|
64
67
|
)
|
65
68
|
|
66
69
|
try:
|
67
70
|
# Execute included object sources FIRST (if any)
|
68
71
|
if included_object_sources:
|
69
|
-
|
72
|
+
logger.debug(
|
73
|
+
"[Worker Code Loader] Executing @include object sources..."
|
74
|
+
) # Changed from print to debug
|
70
75
|
# Include necessary imports for the exec context
|
71
76
|
exec("from pydantic import BaseModel, Field", exec_namespace)
|
72
77
|
exec(
|
@@ -80,49 +85,61 @@ def load_user_code(
|
|
80
85
|
for i, (obj_source, args_sources) in enumerate(included_object_sources):
|
81
86
|
try:
|
82
87
|
exec(obj_source, exec_namespace)
|
83
|
-
print
|
88
|
+
logger.debug( # Changed from print to debug
|
84
89
|
f"[Worker Code Loader] Successfully executed included object {i} base source"
|
85
90
|
)
|
86
91
|
for j, arg_source in enumerate(args_sources):
|
87
92
|
try:
|
88
93
|
exec(arg_source, exec_namespace)
|
89
|
-
print
|
94
|
+
logger.debug( # Changed from print to debug
|
90
95
|
f"[Worker Code Loader] Successfully executed included object {i} arg {j} source"
|
91
96
|
)
|
92
97
|
except Exception as e_arg:
|
93
|
-
print
|
98
|
+
logger.error( # Changed from print to error
|
94
99
|
f"Error executing included object {i} arg {j} source: {e_arg}"
|
95
100
|
)
|
96
|
-
|
101
|
+
logger.exception(
|
102
|
+
f"Included object {i} arg {j} source error:"
|
103
|
+
) # Replaced traceback.print_exc()
|
97
104
|
except Exception as e_base:
|
98
|
-
|
99
|
-
|
100
|
-
|
105
|
+
logger.error(
|
106
|
+
f"Error executing included object {i} base source: {e_base}"
|
107
|
+
) # Changed from print to error
|
108
|
+
logger.exception(
|
109
|
+
f"Included object {i} base source error:"
|
110
|
+
) # Replaced traceback.print_exc()
|
111
|
+
logger.debug(
|
112
|
+
"[Worker Code Loader] Finished executing included object sources."
|
113
|
+
) # Changed from print to debug
|
101
114
|
|
102
115
|
# Import the main module (no reload needed in worker)
|
103
116
|
loaded_module = importlib.import_module(module_path)
|
104
|
-
|
117
|
+
logger.info(
|
118
|
+
f"[Worker Code Loader] Successfully imported module: {module_path}"
|
119
|
+
) # Changed from print
|
105
120
|
|
106
121
|
# Get the target function from the loaded module
|
107
122
|
loaded_target_func = getattr(loaded_module, function_name)
|
108
|
-
print
|
123
|
+
logger.info( # Changed from print
|
109
124
|
f"[Worker Code Loader] Successfully loaded function '{function_name}' from module '{module_path}'"
|
110
125
|
)
|
111
126
|
|
112
127
|
# Get the init function if specified
|
113
128
|
if init_func_name:
|
114
129
|
loaded_init_func = getattr(loaded_module, init_func_name)
|
115
|
-
print
|
130
|
+
logger.info( # Changed from print
|
116
131
|
f"[Worker Code Loader] Successfully loaded init function '{init_func_name}' from module '{module_path}'"
|
117
132
|
)
|
118
133
|
# Execute init_func
|
119
|
-
|
134
|
+
logger.info(
|
135
|
+
f"[Worker Code Loader] Executing init_func: {init_func_name}..."
|
136
|
+
) # Changed from print
|
120
137
|
loaded_init_func() # Call the function
|
121
|
-
print
|
138
|
+
logger.info( # Changed from print
|
122
139
|
f"[Worker Code Loader] Successfully executed init_func: {init_func_name}"
|
123
140
|
)
|
124
141
|
|
125
|
-
|
142
|
+
logger.info("[Worker Code Loader] Code load successful.") # Changed from print
|
126
143
|
return (
|
127
144
|
loaded_target_func,
|
128
145
|
loaded_init_func,
|
@@ -131,28 +148,34 @@ def load_user_code(
|
|
131
148
|
)
|
132
149
|
|
133
150
|
except FileNotFoundError:
|
134
|
-
print
|
151
|
+
logger.error( # Changed from print to error
|
135
152
|
f"[Worker Code Loader] Error: Entrypoint file not found at '{entrypoint_abs_path}'. Cannot load."
|
136
153
|
)
|
137
154
|
return None, None, None, {} # Indicate failure
|
138
155
|
except ImportError as e:
|
139
|
-
|
140
|
-
|
156
|
+
logger.error(
|
157
|
+
f"[Worker Code Loader] Error importing module '{module_path}': {e}"
|
158
|
+
) # Changed from print to error
|
159
|
+
logger.exception("Module import error:") # Replaced traceback.print_exc()
|
141
160
|
return None, None, None, {} # Indicate failure
|
142
161
|
except AttributeError as e:
|
143
|
-
print
|
162
|
+
logger.error( # Changed from print to error
|
144
163
|
f"[Worker Code Loader] Error accessing function '{function_name}' or '{init_func_name}' in module '{module_path}': {e}"
|
145
164
|
)
|
146
|
-
traceback.print_exc()
|
165
|
+
logger.exception("Function access error:") # Replaced traceback.print_exc()
|
147
166
|
return None, None, None, {} # Indicate failure
|
148
167
|
except Exception as e:
|
149
|
-
|
150
|
-
|
168
|
+
logger.error(
|
169
|
+
f"[Worker Code Loader] Unexpected error during code load: {e}"
|
170
|
+
) # Changed from print to error
|
171
|
+
logger.exception(
|
172
|
+
"Unexpected code load error:"
|
173
|
+
) # Replaced traceback.print_exc()
|
151
174
|
return None, None, None, {} # Indicate failure
|
152
175
|
finally:
|
153
176
|
# Unset the guard environment variable
|
154
177
|
os.environ.pop(_NEBU_INSIDE_CONSUMER_ENV_VAR, None)
|
155
|
-
print
|
178
|
+
logger.debug( # Changed from print to debug
|
156
179
|
f"[Worker Code Loader] Unset environment variable {_NEBU_INSIDE_CONSUMER_ENV_VAR}"
|
157
180
|
)
|
158
181
|
|
@@ -171,13 +194,13 @@ def _send_error_response(
|
|
171
194
|
|
172
195
|
# Check if Redis connection exists before trying to use it
|
173
196
|
if r is None:
|
174
|
-
print
|
197
|
+
logger.critical( # Changed from print to critical
|
175
198
|
"[Worker] CRITICAL: Cannot send error response, Redis connection is not available."
|
176
199
|
)
|
177
200
|
return
|
178
201
|
# Assert REDIS_STREAM type here for safety, although it should be set if r is available
|
179
202
|
if not isinstance(redis_stream, str):
|
180
|
-
print
|
203
|
+
logger.critical( # Changed from print to critical
|
181
204
|
"[Worker] CRITICAL: Cannot send error response, REDIS_STREAM is not a valid string."
|
182
205
|
)
|
183
206
|
return
|
@@ -201,19 +224,21 @@ def _send_error_response(
|
|
201
224
|
try:
|
202
225
|
assert isinstance(error_destination, str)
|
203
226
|
r.xadd(error_destination, {"data": json.dumps(error_response)})
|
204
|
-
print
|
227
|
+
logger.info( # Changed from print
|
205
228
|
f"[Worker] Sent error response for message {message_id} to {error_destination}"
|
206
229
|
)
|
207
230
|
except Exception as e_redis:
|
208
|
-
print
|
231
|
+
logger.critical( # Changed from print to critical
|
209
232
|
f"[Worker] CRITICAL: Failed to send error response for {message_id} to Redis: {e_redis}"
|
210
233
|
)
|
211
|
-
|
234
|
+
logger.exception(
|
235
|
+
"Error sending response to Redis:"
|
236
|
+
) # Replaced traceback.print_exc()
|
212
237
|
|
213
238
|
|
214
239
|
# --- Main Worker Logic ---
|
215
240
|
if __name__ == "__main__":
|
216
|
-
|
241
|
+
logger.info("[Worker] Starting subprocess worker...") # Changed from print
|
217
242
|
r: Optional[redis.Redis] = None # Initialize Redis connection variable
|
218
243
|
# Initialize potentially unbound variables
|
219
244
|
message_id: Optional[str] = None
|
@@ -224,24 +249,32 @@ if __name__ == "__main__":
|
|
224
249
|
|
225
250
|
try:
|
226
251
|
# --- 1. Read Input from Stdin ---
|
227
|
-
|
252
|
+
logger.info("[Worker] Reading message data from stdin...") # Changed from print
|
228
253
|
input_data_str = sys.stdin.read()
|
229
254
|
if not input_data_str:
|
230
|
-
|
255
|
+
logger.critical(
|
256
|
+
"[Worker] FATAL: No input data received from stdin."
|
257
|
+
) # Changed from print to critical
|
231
258
|
sys.exit(1)
|
232
259
|
|
233
260
|
try:
|
234
261
|
input_data = json.loads(input_data_str)
|
235
262
|
message_id = input_data["message_id"]
|
236
263
|
message_data = input_data["message_data"]
|
237
|
-
|
264
|
+
logger.info(
|
265
|
+
f"[Worker] Received message_id: {message_id}"
|
266
|
+
) # Changed from print
|
238
267
|
except (json.JSONDecodeError, KeyError) as e:
|
239
|
-
|
268
|
+
logger.critical(
|
269
|
+
f"[Worker] FATAL: Failed to parse input JSON from stdin: {e}"
|
270
|
+
) # Changed from print to critical
|
240
271
|
# Cannot easily send error response without message_id/Redis info
|
241
272
|
sys.exit(1)
|
242
273
|
|
243
274
|
# --- 2. Read Configuration from Environment ---
|
244
|
-
|
275
|
+
logger.info(
|
276
|
+
"[Worker] Reading configuration from environment variables..."
|
277
|
+
) # Changed from print
|
245
278
|
try:
|
246
279
|
# Core function info
|
247
280
|
_function_name = os.environ.get("FUNCTION_NAME")
|
@@ -307,7 +340,7 @@ if __name__ == "__main__":
|
|
307
340
|
if os.path.exists(potential_path):
|
308
341
|
entrypoint_abs_path = potential_path
|
309
342
|
found_path = True
|
310
|
-
print
|
343
|
+
logger.info( # Changed from print
|
311
344
|
f"[Worker] Found entrypoint absolute path via PYTHONPATH: {entrypoint_abs_path}"
|
312
345
|
)
|
313
346
|
break
|
@@ -331,46 +364,62 @@ if __name__ == "__main__":
|
|
331
364
|
f"Could not derive a valid module path from entrypoint '{_entrypoint_rel_path}'"
|
332
365
|
)
|
333
366
|
|
334
|
-
print
|
367
|
+
logger.info( # Changed from print
|
335
368
|
f"[Worker] Config loaded. Module: '{_module_path}', Function: '{_function_name}'"
|
336
369
|
)
|
337
370
|
|
338
371
|
except ValueError as e:
|
339
|
-
|
372
|
+
logger.critical(
|
373
|
+
f"[Worker] FATAL: Configuration error: {e}"
|
374
|
+
) # Changed from print to critical
|
340
375
|
# Cannot send error response without Redis connection
|
341
376
|
sys.exit(1)
|
342
377
|
except Exception as e:
|
343
|
-
|
344
|
-
|
378
|
+
logger.critical(
|
379
|
+
f"[Worker] FATAL: Unexpected error reading environment: {e}"
|
380
|
+
) # Changed from print to critical
|
381
|
+
logger.exception(
|
382
|
+
"Environment reading error:"
|
383
|
+
) # Replaced traceback.print_exc()
|
345
384
|
sys.exit(1)
|
346
385
|
|
347
386
|
# --- 3. Set up SOCKS Proxy ---
|
348
|
-
|
387
|
+
logger.info("[Worker] Configuring SOCKS proxy...") # Changed from print
|
349
388
|
try:
|
350
389
|
socks.set_default_proxy(socks.SOCKS5, "localhost", 1055)
|
351
390
|
socket.socket = socks.socksocket
|
352
|
-
print
|
391
|
+
logger.info( # Changed from print
|
353
392
|
"[Worker] Configured SOCKS5 proxy for socket connections via localhost:1055"
|
354
393
|
)
|
355
394
|
except Exception as e:
|
356
|
-
|
357
|
-
|
395
|
+
logger.critical(
|
396
|
+
f"[Worker] FATAL: Failed to configure SOCKS proxy: {e}"
|
397
|
+
) # Changed from print to critical
|
398
|
+
logger.exception(
|
399
|
+
"SOCKS proxy configuration error:"
|
400
|
+
) # Replaced traceback.print_exc()
|
358
401
|
sys.exit(1)
|
359
402
|
|
360
403
|
# --- 4. Connect to Redis ---
|
361
|
-
|
404
|
+
logger.info("[Worker] Connecting to Redis...") # Changed from print
|
362
405
|
try:
|
363
406
|
r = redis.from_url(REDIS_URL, decode_responses=True)
|
364
407
|
r.ping()
|
365
408
|
redis_info = REDIS_URL.split("@")[-1] if "@" in REDIS_URL else REDIS_URL
|
366
|
-
|
409
|
+
logger.info(
|
410
|
+
f"[Worker] Connected to Redis via SOCKS proxy at {redis_info}"
|
411
|
+
) # Changed from print
|
367
412
|
except Exception as e:
|
368
|
-
|
369
|
-
|
413
|
+
logger.critical(
|
414
|
+
f"[Worker] FATAL: Failed to connect to Redis: {e}"
|
415
|
+
) # Changed from print to critical
|
416
|
+
logger.exception(
|
417
|
+
"Redis connection error:"
|
418
|
+
) # Replaced traceback.print_exc()
|
370
419
|
sys.exit(1) # Cannot proceed without Redis
|
371
420
|
|
372
421
|
# --- 5. Load User Code ---
|
373
|
-
|
422
|
+
logger.info("[Worker] Loading user code...") # Changed from print
|
374
423
|
try:
|
375
424
|
(
|
376
425
|
target_function,
|
@@ -388,11 +437,13 @@ if __name__ == "__main__":
|
|
388
437
|
if target_function is None or imported_module is None:
|
389
438
|
# load_user_code prints errors, just need to exit
|
390
439
|
raise RuntimeError("User code loading failed.")
|
391
|
-
|
440
|
+
logger.info("[Worker] User code loaded successfully.") # Changed from print
|
392
441
|
|
393
442
|
except Exception as e:
|
394
|
-
|
395
|
-
|
443
|
+
logger.error(
|
444
|
+
f"[Worker] Error during user code load: {e}"
|
445
|
+
) # Changed from print to error
|
446
|
+
logger.exception("User code load error:") # Replaced traceback.print_exc()
|
396
447
|
# Send error response via Redis before exiting
|
397
448
|
# Assert message_id is str before sending error
|
398
449
|
assert isinstance(message_id, str)
|
@@ -410,17 +461,19 @@ if __name__ == "__main__":
|
|
410
461
|
# message_id should be str here if code load failed after reading it
|
411
462
|
assert isinstance(message_id, str)
|
412
463
|
r.xack(redis_stream, redis_consumer_group, message_id)
|
413
|
-
print
|
464
|
+
logger.warning( # Changed from print to warning
|
414
465
|
f"[Worker] Acknowledged message {message_id} after code load failure."
|
415
466
|
)
|
416
467
|
except Exception as e_ack:
|
417
|
-
print
|
468
|
+
logger.critical( # Changed from print to critical
|
418
469
|
f"[Worker] CRITICAL: Failed to acknowledge message {message_id} after code load failure: {e_ack}"
|
419
470
|
)
|
420
471
|
sys.exit(1) # Exit after attempting to report failure
|
421
472
|
|
422
473
|
# --- 6. Execute Processing Logic (Adapted from consumer.py inline path) ---
|
423
|
-
|
474
|
+
logger.info(
|
475
|
+
f"[Worker] Processing message {message_id}..."
|
476
|
+
) # Changed from print
|
424
477
|
return_stream = None
|
425
478
|
user_id = None
|
426
479
|
try:
|
@@ -460,7 +513,9 @@ if __name__ == "__main__":
|
|
460
513
|
|
461
514
|
# --- Health Check Logic ---
|
462
515
|
if kind == "HealthCheck":
|
463
|
-
|
516
|
+
logger.info(
|
517
|
+
f"[Worker] Received HealthCheck message {message_id}"
|
518
|
+
) # Changed from print
|
464
519
|
health_response = {
|
465
520
|
"kind": "StreamResponseMessage",
|
466
521
|
"id": message_id, # Respond with original stream message ID
|
@@ -472,9 +527,13 @@ if __name__ == "__main__":
|
|
472
527
|
if return_stream:
|
473
528
|
assert isinstance(return_stream, str)
|
474
529
|
r.xadd(return_stream, {"data": json.dumps(health_response)})
|
475
|
-
|
530
|
+
logger.info(
|
531
|
+
f"[Worker] Sent health check response to {return_stream}"
|
532
|
+
) # Changed from print
|
476
533
|
# Ack handled outside try/except block
|
477
|
-
|
534
|
+
logger.info(
|
535
|
+
f"[Worker] HealthCheck for {message_id} processed successfully."
|
536
|
+
) # Changed from print
|
478
537
|
result_content = None # Indicate healthcheck success path
|
479
538
|
else:
|
480
539
|
# --- Normal Message Processing ---
|
@@ -485,7 +544,7 @@ if __name__ == "__main__":
|
|
485
544
|
content = content_raw
|
486
545
|
else:
|
487
546
|
content = content_raw
|
488
|
-
|
547
|
+
# logger.debug(f"[Worker] Content: {content}") # Changed from print to debug, commented out for less noise
|
489
548
|
|
490
549
|
# --- Construct Input Object ---
|
491
550
|
input_obj: Any = None
|
@@ -505,16 +564,16 @@ if __name__ == "__main__":
|
|
505
564
|
content_model_class = local_namespace.get(
|
506
565
|
content_type_name
|
507
566
|
)
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
567
|
+
if content_model_class is None:
|
568
|
+
logger.warning( # Changed from print to warning
|
569
|
+
f"[Worker] Warning: Content type class '{content_type_name}' not found."
|
570
|
+
)
|
571
|
+
else:
|
572
|
+
logger.debug( # Changed from print to debug
|
573
|
+
f"[Worker] Found content model class: {content_model_class}"
|
574
|
+
)
|
516
575
|
except Exception as e:
|
517
|
-
print
|
576
|
+
logger.warning( # Changed from print to warning
|
518
577
|
f"[Worker] Warning: Error resolving content type class '{content_type_name}': {e}"
|
519
578
|
)
|
520
579
|
|
@@ -523,9 +582,9 @@ if __name__ == "__main__":
|
|
523
582
|
content_model = content_model_class.model_validate(
|
524
583
|
content
|
525
584
|
)
|
526
|
-
print
|
527
|
-
|
528
|
-
)
|
585
|
+
# logger.debug( # Changed from print to debug, commented out
|
586
|
+
# f"[Worker] Validated content model: {content_model}"
|
587
|
+
# )
|
529
588
|
input_obj = message_class(
|
530
589
|
kind=kind,
|
531
590
|
id=msg_id,
|
@@ -539,7 +598,7 @@ if __name__ == "__main__":
|
|
539
598
|
api_key=api_key,
|
540
599
|
)
|
541
600
|
except Exception as e:
|
542
|
-
print
|
601
|
+
logger.error( # Changed from print to error
|
543
602
|
f"[Worker] Error validating/creating content model '{content_type_name}': {e}. Falling back."
|
544
603
|
)
|
545
604
|
input_obj = message_class(
|
@@ -579,18 +638,20 @@ if __name__ == "__main__":
|
|
579
638
|
input_type_class = local_namespace.get(param_type_name)
|
580
639
|
if input_type_class is None:
|
581
640
|
if param_type_name:
|
582
|
-
print
|
641
|
+
logger.warning( # Changed from print to warning
|
583
642
|
f"[Worker] Warning: Input type class '{param_type_name}' not found. Passing raw."
|
584
643
|
)
|
585
644
|
input_obj = content
|
586
645
|
else:
|
587
|
-
print
|
646
|
+
logger.debug( # Changed from print to debug
|
588
647
|
f"[Worker] Found input model class: {input_type_class}"
|
589
648
|
)
|
590
649
|
input_obj = input_type_class.model_validate(content)
|
591
|
-
|
650
|
+
logger.debug(
|
651
|
+
f"[Worker] Validated input model: {input_obj}"
|
652
|
+
) # Changed from print to debug
|
592
653
|
except Exception as e:
|
593
|
-
print
|
654
|
+
logger.error( # Changed from print to error
|
594
655
|
f"[Worker] Error resolving/validating input type '{param_type_name}': {e}. Passing raw."
|
595
656
|
)
|
596
657
|
input_obj = content
|
@@ -600,13 +661,19 @@ if __name__ == "__main__":
|
|
600
661
|
f"Required class not found (e.g., Message or param type): {e}"
|
601
662
|
) from e
|
602
663
|
except Exception as e:
|
603
|
-
|
664
|
+
logger.error(
|
665
|
+
f"[Worker] Error constructing input object: {e}"
|
666
|
+
) # Changed from print to error
|
604
667
|
raise
|
605
668
|
|
606
669
|
# --- Execute the Function ---
|
607
|
-
|
670
|
+
logger.info(
|
671
|
+
f"[Worker] Executing function '{_function_name}'..."
|
672
|
+
) # Changed from print
|
608
673
|
result = target_function(input_obj)
|
609
|
-
|
674
|
+
logger.debug(
|
675
|
+
f"[Worker] Result: {result}"
|
676
|
+
) # Changed from print to debug
|
610
677
|
|
611
678
|
# --- Convert Result ---
|
612
679
|
if hasattr(result, "model_dump"):
|
@@ -629,7 +696,7 @@ if __name__ == "__main__":
|
|
629
696
|
if return_stream:
|
630
697
|
assert isinstance(return_stream, str)
|
631
698
|
r.xadd(return_stream, {"data": json.dumps(response)})
|
632
|
-
print
|
699
|
+
logger.info( # Changed from print
|
633
700
|
f"[Worker] Processed message {message_id}, result sent to {return_stream}"
|
634
701
|
)
|
635
702
|
|
@@ -640,17 +707,21 @@ if __name__ == "__main__":
|
|
640
707
|
message_id, str
|
641
708
|
) # message_id is str if processing succeeded
|
642
709
|
r.xack(redis_stream, redis_consumer_group, message_id)
|
643
|
-
|
710
|
+
logger.info(
|
711
|
+
f"[Worker] Acknowledged message {message_id} successfully."
|
712
|
+
) # Changed from print
|
644
713
|
|
645
714
|
# --- 9. Exit Successfully ---
|
646
|
-
|
715
|
+
logger.info("[Worker] Exiting with status 0.") # Changed from print
|
647
716
|
sys.exit(0)
|
648
717
|
|
649
718
|
except RetriableError as e:
|
650
719
|
# --- Handle Retriable Processing Error ---
|
651
|
-
|
720
|
+
logger.warning(
|
721
|
+
f"[Worker] Retriable error processing message {message_id}: {e}"
|
722
|
+
) # Changed from print to warning
|
652
723
|
tb = traceback.format_exc()
|
653
|
-
|
724
|
+
# logger.exception("Retriable error details:") # Use logger.exception instead of printing tb
|
654
725
|
# Assert message_id is str before sending error
|
655
726
|
assert isinstance(message_id, str)
|
656
727
|
# Send error response (optional, consider suppressing later if too noisy)
|
@@ -659,14 +730,18 @@ if __name__ == "__main__":
|
|
659
730
|
# DO NOT Acknowledge the message for retriable errors
|
660
731
|
|
661
732
|
# --- 9. Exit with specific code for retriable failure ---
|
662
|
-
|
733
|
+
logger.warning(
|
734
|
+
"[Worker] Exiting with status 3 due to retriable error."
|
735
|
+
) # Changed from print to warning
|
663
736
|
sys.exit(3)
|
664
737
|
|
665
738
|
except Exception as e:
|
666
739
|
# --- Handle Non-Retriable Processing Error ---
|
667
|
-
|
740
|
+
logger.error(
|
741
|
+
f"[Worker] Error processing message {message_id}: {e}"
|
742
|
+
) # Changed from print to error
|
668
743
|
tb = traceback.format_exc()
|
669
|
-
|
744
|
+
# logger.exception("Processing error details:") # Use logger.exception instead of printing tb
|
670
745
|
# Assert message_id is str before sending error
|
671
746
|
assert isinstance(message_id, str)
|
672
747
|
_send_error_response(message_id, str(e), tb, return_stream, user_id)
|
@@ -678,21 +753,27 @@ if __name__ == "__main__":
|
|
678
753
|
# message_id is str if processing failed after reading it
|
679
754
|
assert isinstance(message_id, str)
|
680
755
|
r.xack(redis_stream, redis_consumer_group, message_id)
|
681
|
-
|
756
|
+
logger.info(
|
757
|
+
f"[Worker] Acknowledged failed message {message_id}"
|
758
|
+
) # Changed from print
|
682
759
|
except Exception as e_ack:
|
683
|
-
print
|
760
|
+
logger.critical( # Changed from print to critical
|
684
761
|
f"[Worker] CRITICAL: Failed to acknowledge failed message {message_id}: {e_ack}"
|
685
762
|
)
|
686
763
|
|
687
764
|
# --- 9. Exit with Failure ---
|
688
|
-
|
765
|
+
logger.error(
|
766
|
+
"[Worker] Exiting with status 1 due to processing error."
|
767
|
+
) # Changed from print to error
|
689
768
|
sys.exit(1)
|
690
769
|
|
691
770
|
except Exception as outer_e:
|
692
771
|
# --- Handle Catastrophic Worker Error (e.g., setup failure) ---
|
693
|
-
|
772
|
+
logger.critical(
|
773
|
+
f"[Worker] FATAL outer error: {outer_e}"
|
774
|
+
) # Changed from print to critical
|
694
775
|
tb = traceback.format_exc()
|
695
|
-
|
776
|
+
# logger.exception("Fatal worker error:") # Use logger.exception instead of printing tb
|
696
777
|
# If Redis was connected, try to send a generic error for the message_id read from stdin
|
697
778
|
# Check that all required variables are not None before proceeding
|
698
779
|
if (
|
@@ -716,17 +797,19 @@ if __name__ == "__main__":
|
|
716
797
|
)
|
717
798
|
# Attempt to ack if possible, even though the main consumer *might* also try
|
718
799
|
r.xack(redis_stream, redis_consumer_group, message_id)
|
719
|
-
print
|
800
|
+
logger.warning( # Changed from print to warning
|
720
801
|
f"[Worker] Attempted to acknowledge message {message_id} after fatal error."
|
721
802
|
)
|
722
803
|
except Exception as final_e:
|
723
|
-
print
|
804
|
+
logger.critical( # Changed from print to critical
|
724
805
|
f"[Worker] CRITICAL: Failed during final error reporting/ack: {final_e}"
|
725
806
|
)
|
726
807
|
else:
|
727
|
-
print
|
808
|
+
logger.critical( # Changed from print to critical
|
728
809
|
"[Worker] CRITICAL: Could not report final error or ack message due to missing Redis connection or message details."
|
729
810
|
)
|
730
811
|
|
731
|
-
|
812
|
+
logger.critical(
|
813
|
+
"[Worker] Exiting with status 1 due to fatal error."
|
814
|
+
) # Changed from print to critical
|
732
815
|
sys.exit(1)
|