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.
@@ -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
- print(f"[Worker Code Loader] Attempting to load module: '{module_path}'")
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
- print("[Worker Code Loader] Executing @include object sources...")
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
- traceback.print_exc()
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
- print(f"Error executing included object {i} base source: {e_base}")
99
- traceback.print_exc()
100
- print("[Worker Code Loader] Finished executing included object sources.")
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
- print(f"[Worker Code Loader] Successfully imported module: {module_path}")
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
- print(f"[Worker Code Loader] Executing init_func: {init_func_name}...")
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
- print("[Worker Code Loader] Code load successful.")
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
- print(f"[Worker Code Loader] Error importing module '{module_path}': {e}")
140
- traceback.print_exc()
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
- print(f"[Worker Code Loader] Unexpected error during code load: {e}")
150
- traceback.print_exc()
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
- traceback.print_exc()
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
- print("[Worker] Starting subprocess worker...")
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
- print("[Worker] Reading message data from stdin...")
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
- print("[Worker] FATAL: No input data received from stdin.")
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
- print(f"[Worker] Received message_id: {message_id}")
264
+ logger.info(
265
+ f"[Worker] Received message_id: {message_id}"
266
+ ) # Changed from print
238
267
  except (json.JSONDecodeError, KeyError) as e:
239
- print(f"[Worker] FATAL: Failed to parse input JSON from stdin: {e}")
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
- print("[Worker] Reading configuration from environment variables...")
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
- print(f"[Worker] FATAL: Configuration error: {e}")
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
- print(f"[Worker] FATAL: Unexpected error reading environment: {e}")
344
- traceback.print_exc()
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
- print("[Worker] Configuring SOCKS proxy...")
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
- print(f"[Worker] FATAL: Failed to configure SOCKS proxy: {e}")
357
- traceback.print_exc()
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
- print("[Worker] Connecting to Redis...")
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
- print(f"[Worker] Connected to Redis via SOCKS proxy at {redis_info}")
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
- print(f"[Worker] FATAL: Failed to connect to Redis: {e}")
369
- traceback.print_exc()
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
- print("[Worker] Loading user code...")
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
- print("[Worker] User code loaded successfully.")
440
+ logger.info("[Worker] User code loaded successfully.") # Changed from print
392
441
 
393
442
  except Exception as e:
394
- print(f"[Worker] Error during user code load: {e}")
395
- traceback.print_exc()
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
- print(f"[Worker] Processing message {message_id}...")
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
- print(f"[Worker] Received HealthCheck message {message_id}")
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
- print(f"[Worker] Sent health check response to {return_stream}")
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
- print(f"[Worker] HealthCheck for {message_id} processed successfully.")
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
- print(f"[Worker] Content: {content}")
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
- if content_model_class is None:
509
- print(
510
- f"[Worker] Warning: Content type class '{content_type_name}' not found."
511
- )
512
- else:
513
- print(
514
- f"[Worker] Found content model class: {content_model_class}"
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
- f"[Worker] Validated content model: {content_model}"
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
- print(f"[Worker] Validated input model: {input_obj}")
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
- print(f"[Worker] Error constructing input object: {e}")
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
- print(f"[Worker] Executing function '{_function_name}'...")
670
+ logger.info(
671
+ f"[Worker] Executing function '{_function_name}'..."
672
+ ) # Changed from print
608
673
  result = target_function(input_obj)
609
- print(f"[Worker] Result: {result}")
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
- print(f"[Worker] Acknowledged message {message_id} successfully.")
710
+ logger.info(
711
+ f"[Worker] Acknowledged message {message_id} successfully."
712
+ ) # Changed from print
644
713
 
645
714
  # --- 9. Exit Successfully ---
646
- print("[Worker] Exiting with status 0.")
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
- print(f"[Worker] Retriable error processing message {message_id}: {e}")
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
- print(tb)
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
- print("[Worker] Exiting with status 3 due to retriable error.")
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
- print(f"[Worker] Error processing message {message_id}: {e}")
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
- print(tb)
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
- print(f"[Worker] Acknowledged failed message {message_id}")
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
- print("[Worker] Exiting with status 1 due to processing error.")
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
- print(f"[Worker] FATAL outer error: {outer_e}")
772
+ logger.critical(
773
+ f"[Worker] FATAL outer error: {outer_e}"
774
+ ) # Changed from print to critical
694
775
  tb = traceback.format_exc()
695
- print(tb)
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
- print("[Worker] Exiting with status 1 due to fatal error.")
812
+ logger.critical(
813
+ "[Worker] Exiting with status 1 due to fatal error."
814
+ ) # Changed from print to critical
732
815
  sys.exit(1)