redis-allocator 0.0.1__py3-none-any.whl → 0.3.1__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.
tests/test_task_queue.py CHANGED
@@ -37,19 +37,19 @@ class TestRedisTaskQueue:
37
37
  # Create and set a task
38
38
  task = task_queue.build_task("task1", "test", {"param1": "value1"})
39
39
  task_id = task_queue.set_task(task)
40
-
40
+
41
41
  # Mock the pickle and base64 operations to avoid serialization issues
42
42
  task_copy = task_queue.build_task("task1", "test", {"param1": "value1"})
43
-
43
+
44
44
  # Verify the task was saved
45
45
  assert task_id == "task1"
46
46
  assert redis_client.exists(task_queue._result_key("task1"))
47
-
47
+
48
48
  # Patch the get_task method to return our mocked task
49
49
  original_get_task = task_queue.get_task
50
50
  try:
51
51
  task_queue.get_task = lambda task_id, once=False: task_copy
52
-
52
+
53
53
  # Get the task back
54
54
  retrieved_task = task_queue.get_task("task1")
55
55
  assert retrieved_task.id == "task1"
@@ -64,10 +64,10 @@ class TestRedisTaskQueue:
64
64
  # Create and set a task
65
65
  task = task_queue.build_task("task1", "test", {"param1": "value1"})
66
66
  task_queue.set_task(task)
67
-
67
+
68
68
  # Verify task exists
69
69
  assert task_queue.has_task("task1") is True
70
-
70
+
71
71
  # Verify non-existent task doesn't exist
72
72
  assert task_queue.has_task("task2") is False
73
73
 
@@ -75,7 +75,7 @@ class TestRedisTaskQueue:
75
75
  """Test executing a task locally."""
76
76
  task = task_queue.build_task("task1", "test", {"param1": "value1"})
77
77
  result = task_queue.execute_task_locally(task)
78
-
78
+
79
79
  assert result == "result-task1"
80
80
  assert task.result == "result-task1"
81
81
  assert task.error is None
@@ -84,15 +84,15 @@ class TestRedisTaskQueue:
84
84
  """Test local execution with an error."""
85
85
  # Set up a task that will fail
86
86
  task = task_queue.build_task("error_task", "test", {"param1": "value1"})
87
-
87
+
88
88
  # Mock the task_fn to raise an exception
89
89
  error = ValueError("Test error")
90
90
  mocker.patch.object(task_queue, 'task_fn', side_effect=error)
91
-
91
+
92
92
  # Execute the task and verify it fails properly
93
93
  with pytest.raises(ValueError, match="Test error"):
94
94
  task_queue.execute_task_locally(task)
95
-
95
+
96
96
  # Verify the error was captured in the task
97
97
  assert task.error == error
98
98
  assert task.result is None
@@ -101,14 +101,14 @@ class TestRedisTaskQueue:
101
101
  """Test remote task execution."""
102
102
  # Create a task
103
103
  task = task_queue.build_task("task2", "test", {"param1": "value2"})
104
-
104
+
105
105
  # Set up a listener for the test queue
106
106
  task_queue.set_queue_listened("test")
107
-
107
+
108
108
  # Start a thread that will listen for the task and execute it
109
109
  # (Simulating a remote worker)
110
110
  processed_event = threading.Event()
111
-
111
+
112
112
  def process_task():
113
113
  # Get the task from the queue
114
114
  queue_key = task_queue._queue_key("test")
@@ -122,36 +122,36 @@ class TestRedisTaskQueue:
122
122
  task.result = result
123
123
  task.save()
124
124
  processed_event.set()
125
-
125
+
126
126
  # Start the worker thread
127
127
  worker_thread = threading.Thread(target=process_task)
128
128
  worker_thread.daemon = True
129
129
  worker_thread.start()
130
-
130
+
131
131
  try:
132
132
  # Replace execute_task_remotely with our own implementation
133
133
  def mock_execute_remotely(task, timeout=None, once=False):
134
134
  # Push the task to Redis queue
135
135
  task_queue.set_task(task)
136
136
  redis_client.rpush(task_queue._queue_key(task.name), task.id)
137
-
137
+
138
138
  # Wait for worker to process it (with a reasonable timeout)
139
139
  if not processed_event.wait(timeout=3):
140
140
  raise TimeoutError("Worker did not process task within timeout")
141
-
141
+
142
142
  # Get the processed task with result
143
143
  processed_task = task_queue.get_task(task.id, once)
144
144
  return processed_task.result
145
-
145
+
146
146
  # Apply the mock
147
147
  mocker.patch.object(task_queue, 'execute_task_remotely', side_effect=mock_execute_remotely)
148
-
148
+
149
149
  # Execute the task remotely
150
150
  result = task_queue.execute_task_remotely(task, timeout=3)
151
-
151
+
152
152
  # Verify the result
153
153
  assert result == f"result-{task.id}"
154
-
154
+
155
155
  finally:
156
156
  # Make sure thread is done
157
157
  worker_thread.join(timeout=1)
@@ -160,14 +160,14 @@ class TestRedisTaskQueue:
160
160
  """Test remote execution with an error."""
161
161
  # Create a task that will fail remotely
162
162
  task = task_queue.build_task("error_remote", "test", {"param1": "value3"})
163
-
163
+
164
164
  # Set up a listener for the test queue
165
165
  task_queue.set_queue_listened("test")
166
-
166
+
167
167
  # Start a thread that will listen for the task and execute it with an error
168
168
  # (Simulating a remote worker)
169
169
  processed_event = threading.Event()
170
-
170
+
171
171
  def process_task():
172
172
  # Get the task from the queue
173
173
  queue_key = task_queue._queue_key("test")
@@ -180,17 +180,17 @@ class TestRedisTaskQueue:
180
180
  task.error = ValueError("Remote error")
181
181
  task.save()
182
182
  processed_event.set()
183
-
183
+
184
184
  # Start the worker thread
185
185
  worker_thread = threading.Thread(target=process_task)
186
186
  worker_thread.daemon = True
187
187
  worker_thread.start()
188
-
188
+
189
189
  # Execute the task remotely and expect an error
190
190
  try:
191
191
  with pytest.raises(ValueError, match="Remote error"):
192
192
  task_queue.execute_task_remotely(task, timeout=3)
193
-
193
+
194
194
  # Verify the thread processed the task
195
195
  assert processed_event.is_set()
196
196
  finally:
@@ -201,21 +201,21 @@ class TestRedisTaskQueue:
201
201
  """Test remote execution with timeout."""
202
202
  # Create a task
203
203
  task = task_queue.build_task("timeout_task", "test", {"param1": "value4"})
204
-
204
+
205
205
  # Set timeout to a very small value to ensure it times out
206
206
  timeout = 0.1
207
-
207
+
208
208
  # Mock time.sleep to avoid actual sleeping
209
209
  time_sleep_mock = mocker.patch('time.sleep')
210
-
210
+
211
211
  # Mock get_task to always return None (simulating no worker processing the task)
212
212
  mocker.patch.object(task_queue, 'get_task', return_value=None)
213
-
213
+
214
214
  # Use a task that will not get processed by any worker
215
215
  # Execute the task remotely with a small timeout and expect a timeout
216
216
  with pytest.raises(TimeoutError):
217
217
  task_queue.execute_task_remotely(task, timeout=timeout)
218
-
218
+
219
219
  # Verify time.sleep was called at least once
220
220
  time_sleep_mock.assert_called()
221
221
 
@@ -223,7 +223,7 @@ class TestRedisTaskQueue:
223
223
  """Test query with local execution policy."""
224
224
  # Call query with local policy
225
225
  result = task_queue.query("task3", "test", {}, policy=TaskExecutePolicy.Local)
226
-
226
+
227
227
  # Verify result
228
228
  assert result == "result-task3"
229
229
 
@@ -231,11 +231,11 @@ class TestRedisTaskQueue:
231
231
  """Test query with remote execution policy."""
232
232
  # Set up a listener for the test queue
233
233
  task_queue.set_queue_listened("test")
234
-
234
+
235
235
  # Start a thread that will listen for the task and execute it
236
236
  # (Simulating a remote worker)
237
237
  processed_event = threading.Event()
238
-
238
+
239
239
  def process_task():
240
240
  # Get the task from the queue
241
241
  queue_key = task_queue._queue_key("test")
@@ -249,33 +249,33 @@ class TestRedisTaskQueue:
249
249
  task.result = result
250
250
  task.save()
251
251
  processed_event.set()
252
-
252
+
253
253
  # Start the worker thread
254
254
  worker_thread = threading.Thread(target=process_task)
255
255
  worker_thread.daemon = True
256
256
  worker_thread.start()
257
-
257
+
258
258
  try:
259
259
  # Replace execute_task_remotely with our own implementation
260
260
  def mock_execute_remotely(task, timeout=None, once=False):
261
261
  # Push the task to Redis queue
262
262
  task_queue.set_task(task)
263
263
  redis_client.rpush(task_queue._queue_key(task.name), task.id)
264
-
264
+
265
265
  # Wait for worker to process it (with a reasonable timeout)
266
266
  if not processed_event.wait(timeout=3):
267
267
  raise TimeoutError("Worker did not process task within timeout")
268
-
268
+
269
269
  # Get the processed task with result
270
270
  processed_task = task_queue.get_task(task.id, once)
271
271
  return processed_task.result
272
-
272
+
273
273
  # Apply the mock
274
274
  mocker.patch.object(task_queue, 'execute_task_remotely', side_effect=mock_execute_remotely)
275
-
275
+
276
276
  # Call query with remote policy
277
277
  result = task_queue.query("task4", "test", {}, policy=TaskExecutePolicy.Remote, timeout=3)
278
-
278
+
279
279
  # Verify result
280
280
  assert result == "result-task4"
281
281
  finally:
@@ -286,7 +286,7 @@ class TestRedisTaskQueue:
286
286
  """Test query with local-first execution policy."""
287
287
  # Call query with local-first policy
288
288
  result = task_queue.query("task5", "test", {}, policy=TaskExecutePolicy.LocalFirst)
289
-
289
+
290
290
  # Verify result - should execute locally
291
291
  assert result == "result-task5"
292
292
 
@@ -295,17 +295,17 @@ class TestRedisTaskQueue:
295
295
  # We'll only mock the task_fn to simulate a local execution failure
296
296
  error = ValueError("Local error")
297
297
  mocker.patch.object(task_queue, 'task_fn', side_effect=error)
298
-
298
+
299
299
  # Mock logger.exception to prevent actual logging
300
300
  mocker.patch('redis_allocator.task_queue.logger.exception')
301
-
301
+
302
302
  # Set up a listener for the test queue
303
303
  task_queue.set_queue_listened("test")
304
-
304
+
305
305
  # Start a thread that will listen for the task and execute it
306
306
  # (Simulating a remote worker)
307
307
  processed_event = threading.Event()
308
-
308
+
309
309
  def process_task():
310
310
  # Get the task from the queue
311
311
  queue_key = task_queue._queue_key("test")
@@ -319,36 +319,36 @@ class TestRedisTaskQueue:
319
319
  task.result = f"remote-result-{task.id}"
320
320
  task.save()
321
321
  processed_event.set()
322
-
322
+
323
323
  # Start the worker thread
324
324
  worker_thread = threading.Thread(target=process_task)
325
325
  worker_thread.daemon = True
326
326
  worker_thread.start()
327
-
327
+
328
328
  try:
329
329
  # Make the execute_task_remotely method faster by skipping actual sleep
330
330
  def mocked_execute_remotely(task, timeout=None, once=False):
331
331
  # Push to queue but skip the actual sleeping
332
332
  redis_client.rpush(task_queue._queue_key(task.name), task.id)
333
-
333
+
334
334
  # Wait a moment for the worker thread to process
335
335
  processed_event.wait(timeout=1)
336
-
336
+
337
337
  # Get the task with result
338
338
  result = task_queue.get_task(task.id, once)
339
339
  if result is not None and result.result is not None:
340
340
  return result.result
341
341
  raise TimeoutError(f'Task {task.id} in {task.name} has expired')
342
-
342
+
343
343
  # Replace with mock
344
344
  mocker.patch.object(task_queue, 'execute_task_remotely', side_effect=mocked_execute_remotely)
345
-
345
+
346
346
  # Call query with local-first policy (which should fail locally and fall back to remote)
347
347
  result = task_queue.query("task6", "test", {}, policy=TaskExecutePolicy.LocalFirst, timeout=3)
348
-
348
+
349
349
  # Verify the thread processed the task
350
350
  assert processed_event.is_set()
351
-
351
+
352
352
  # Verify result from remote execution
353
353
  assert result == "remote-result-task6"
354
354
  finally:
@@ -359,11 +359,11 @@ class TestRedisTaskQueue:
359
359
  """Test query with remote-first execution policy."""
360
360
  # Set up a listener for the test queue
361
361
  task_queue.set_queue_listened("test")
362
-
362
+
363
363
  # Start a thread that will listen for the task and execute it
364
364
  # (Simulating a remote worker)
365
365
  processed_event = threading.Event()
366
-
366
+
367
367
  def process_task():
368
368
  # Get the task from the queue
369
369
  queue_key = task_queue._queue_key("test")
@@ -376,33 +376,33 @@ class TestRedisTaskQueue:
376
376
  task.result = f"remote-result-{task.id}"
377
377
  task.save()
378
378
  processed_event.set()
379
-
379
+
380
380
  # Start the worker thread
381
381
  worker_thread = threading.Thread(target=process_task)
382
382
  worker_thread.daemon = True
383
383
  worker_thread.start()
384
-
384
+
385
385
  try:
386
386
  # Replace execute_task_remotely with our own implementation
387
387
  def mock_execute_remotely(task, timeout=None, once=False):
388
388
  # Push the task to Redis queue
389
389
  task_queue.set_task(task)
390
390
  redis_client.rpush(task_queue._queue_key(task.name), task.id)
391
-
391
+
392
392
  # Wait for worker to process it (with a reasonable timeout)
393
393
  if not processed_event.wait(timeout=3):
394
394
  raise TimeoutError("Worker did not process task within timeout")
395
-
395
+
396
396
  # Get the processed task with result
397
397
  processed_task = task_queue.get_task(task.id, once)
398
398
  return processed_task.result
399
-
399
+
400
400
  # Apply the mock
401
401
  mocker.patch.object(task_queue, 'execute_task_remotely', side_effect=mock_execute_remotely)
402
-
402
+
403
403
  # Call query with remote-first policy
404
404
  result = task_queue.query("task7", "test", {}, policy=TaskExecutePolicy.RemoteFirst, timeout=3)
405
-
405
+
406
406
  # Verify result
407
407
  assert result == "remote-result-task7"
408
408
  finally:
@@ -414,18 +414,18 @@ class TestRedisTaskQueue:
414
414
  # We'll mock execute_task_remotely to fail
415
415
  # This simulates a remote execution failure more reliably
416
416
  mocker.patch.object(
417
- task_queue,
418
- 'execute_task_remotely',
417
+ task_queue,
418
+ 'execute_task_remotely',
419
419
  side_effect=TimeoutError("No remote listeners available")
420
420
  )
421
-
421
+
422
422
  # Mock logger.exception to prevent actual logging
423
423
  mocker.patch('redis_allocator.task_queue.logger.exception')
424
-
424
+
425
425
  # Call query with remote-first policy
426
426
  # The remote execution should fail, and it will fall back to local
427
427
  result = task_queue.query("task8", "test", {}, policy=TaskExecutePolicy.RemoteFirst)
428
-
428
+
429
429
  # Verify local result (since remote failed)
430
430
  assert result == "result-task8"
431
431
 
@@ -433,11 +433,11 @@ class TestRedisTaskQueue:
433
433
  """Test query with auto policy when a listener exists."""
434
434
  # Set up a listener for the test queue
435
435
  task_queue.set_queue_listened("test")
436
-
436
+
437
437
  # Start a thread that will listen for the task and execute it
438
438
  # (Simulating a remote worker)
439
439
  processed_event = threading.Event()
440
-
440
+
441
441
  def process_task():
442
442
  # Get the task from the queue
443
443
  queue_key = task_queue._queue_key("test")
@@ -450,33 +450,33 @@ class TestRedisTaskQueue:
450
450
  task.result = f"remote-result-{task.id}"
451
451
  task.save()
452
452
  processed_event.set()
453
-
453
+
454
454
  # Start the worker thread
455
455
  worker_thread = threading.Thread(target=process_task)
456
456
  worker_thread.daemon = True
457
457
  worker_thread.start()
458
-
458
+
459
459
  try:
460
460
  # Replace execute_task_remotely with our own implementation
461
461
  def mock_execute_remotely(task, timeout=None, once=False):
462
462
  # Push the task to Redis queue
463
463
  task_queue.set_task(task)
464
464
  redis_client.rpush(task_queue._queue_key(task.name), task.id)
465
-
465
+
466
466
  # Wait for worker to process it (with a reasonable timeout)
467
467
  if not processed_event.wait(timeout=3):
468
468
  raise TimeoutError("Worker did not process task within timeout")
469
-
469
+
470
470
  # Get the processed task with result
471
471
  processed_task = task_queue.get_task(task.id, once)
472
472
  return processed_task.result
473
-
473
+
474
474
  # Apply the mock
475
475
  mocker.patch.object(task_queue, 'execute_task_remotely', side_effect=mock_execute_remotely)
476
-
476
+
477
477
  # Call query with auto policy when a listener exists - should execute remotely
478
478
  result = task_queue.query("task9", "test", {}, policy=TaskExecutePolicy.Auto, timeout=3)
479
-
479
+
480
480
  # Verify result from remote execution
481
481
  assert result == "remote-result-task9"
482
482
  finally:
@@ -487,10 +487,10 @@ class TestRedisTaskQueue:
487
487
  """Test query with auto policy when no listener exists."""
488
488
  # Make sure there is no active listener
489
489
  # Just don't call set_queue_listened()
490
-
490
+
491
491
  # Call query with auto policy when no listener exists - should execute locally
492
492
  result = task_queue.query("task10", "test", {}, policy=TaskExecutePolicy.Auto)
493
-
493
+
494
494
  # Verify result from local execution
495
495
  assert result == "result-task10"
496
496
 
@@ -498,16 +498,16 @@ class TestRedisTaskQueue:
498
498
  """Test updating task progress."""
499
499
  # Create a task
500
500
  task = task_queue.build_task("task11", "test", {"param1": "value1"})
501
-
501
+
502
502
  # Fixed time for consistent testing
503
503
  fixed_time_str = "2022-04-15T10:00:00Z" # 使用UTC时间
504
504
  dt = datetime.datetime.fromisoformat(fixed_time_str.replace('Z', '+00:00'))
505
-
505
+
506
506
  # Use freezegun to set a fixed time
507
507
  with freeze_time(dt):
508
508
  # Update progress
509
509
  task.update(50.0, 100.0)
510
-
510
+
511
511
  # Verify progress was updated
512
512
  assert task.current_progress == 50.0
513
513
  assert task.total_progress == 100.0
@@ -517,7 +517,7 @@ class TestRedisTaskQueue:
517
517
  """Test updating progress for an expired task."""
518
518
  # Current time for reference
519
519
  current_time = time.time()
520
-
520
+
521
521
  # Create a task with expiry in the past (100 seconds ago)
522
522
  with freeze_time(datetime.datetime.fromtimestamp(current_time - 200)): # Create a time point far in the past
523
523
  # Create task with expiry = current_time - 100 (which is expired from current perspective)
@@ -528,7 +528,7 @@ class TestRedisTaskQueue:
528
528
  expiry=current_time - 100, # Set expiry to be 100 seconds before current time
529
529
  _save=lambda: None
530
530
  )
531
-
531
+
532
532
  # Move to current time and try to update the expired task
533
533
  with freeze_time(datetime.datetime.fromtimestamp(current_time)):
534
534
  # Try to update progress and expect TimeoutError
@@ -540,42 +540,42 @@ class TestRedisTaskQueue:
540
540
  # Set up task queue names
541
541
  names = ['test_queue']
542
542
  queue_key = task_queue._queue_key(names[0])
543
-
543
+
544
544
  # Create a task to be processed
545
545
  task = task_queue.build_task("listen_task", "test_queue", {"param": "value"})
546
-
546
+
547
547
  # Save the task
548
548
  task_queue.set_task(task)
549
-
549
+
550
550
  # Directly push task ID to queue
551
551
  redis_client.rpush(queue_key, task.id)
552
-
552
+
553
553
  # Manually run one iteration of the listen loop
554
554
  # This avoids the infinite loop in the actual listen method
555
555
  queue_names = [task_queue._queue_key(name) for name in names]
556
-
556
+
557
557
  # Process task
558
558
  task_data = redis_client.blpop(queue_names, timeout=task_queue.interval)
559
559
  assert task_data is not None
560
-
560
+
561
561
  _queue_key, task_id = task_data
562
562
  # 检查task_id的类型并处理
563
563
  if isinstance(task_id, bytes):
564
564
  task_id = task_id.decode('utf-8')
565
565
  assert task_id == "listen_task"
566
-
566
+
567
567
  # Get the task
568
568
  task = task_queue.get_task(task_id)
569
569
  assert task is not None
570
-
570
+
571
571
  # Execute task locally to verify
572
572
  result = task_queue.execute_task_locally(task)
573
573
  assert result == "result-listen_task"
574
-
574
+
575
575
  # Mark queues as listened
576
576
  for name in names:
577
577
  task_queue.set_queue_listened(name)
578
-
578
+
579
579
  # Verify that the queue is marked as listened
580
580
  assert redis_client.exists(task_queue._queue_listen_name(names[0])) > 0
581
581
 
@@ -583,13 +583,13 @@ class TestRedisTaskQueue:
583
583
  """Test the listen method using a separate thread to avoid blocking the test."""
584
584
  # Set up task queue names
585
585
  names = ['test_queue']
586
-
586
+
587
587
  # Create a task to be processed
588
588
  task = task_queue.build_task("listen_task", "test_queue", {"param": "value"})
589
-
589
+
590
590
  # Patch methods to avoid actual Redis operations
591
591
  mocker.patch.object(task_queue, 'set_task')
592
-
592
+
593
593
  # Mock blpop to return our task ID first, then always return None
594
594
  # This avoids StopIteration exception in the thread
595
595
  def mock_blpop_side_effect(*args, **kwargs):
@@ -598,51 +598,51 @@ class TestRedisTaskQueue:
598
598
  mock_blpop_side_effect.called = True
599
599
  return (task_queue._queue_key('test_queue'), b"listen_task")
600
600
  return None
601
-
601
+
602
602
  mocker.patch.object(redis_client, 'blpop', side_effect=mock_blpop_side_effect)
603
-
603
+
604
604
  # Mock get_task to return our task
605
605
  mocker.patch.object(task_queue, 'get_task', return_value=task)
606
-
606
+
607
607
  # Track when task is executed
608
608
  task_executed = threading.Event()
609
-
609
+
610
610
  def mock_execute_task(t):
611
611
  # Mark that the task was executed and return a result
612
612
  task_executed.set()
613
613
  return "result"
614
-
614
+
615
615
  mocker.patch.object(task_queue, 'execute_task_locally', side_effect=mock_execute_task)
616
-
616
+
617
617
  # Use freezegun to handle the sleep in the listen method
618
618
  current_time = time.time()
619
619
  with freeze_time(datetime.datetime.fromtimestamp(current_time)) as frozen_time:
620
620
  # Replace time.sleep to advance the frozen time
621
621
  original_sleep = time.sleep
622
-
622
+
623
623
  def advance_time(seconds):
624
624
  frozen_time.tick(datetime.timedelta(seconds=seconds))
625
-
625
+
626
626
  time.sleep = advance_time
627
-
627
+
628
628
  try:
629
629
  # Run listen in a separate thread with a stop event
630
630
  stop_event = threading.Event()
631
-
631
+
632
632
  # Start a thread that will call listen for a short time
633
633
  listen_thread = threading.Thread(
634
634
  target=lambda: task_queue.listen(names, event=stop_event, workers=1)
635
635
  )
636
636
  listen_thread.daemon = True # Ensure thread doesn't block test exit
637
637
  listen_thread.start()
638
-
638
+
639
639
  # Wait for the task to be executed or timeout
640
640
  executed = task_executed.wait(timeout=5)
641
-
641
+
642
642
  # Stop the listen thread
643
643
  stop_event.set()
644
644
  listen_thread.join(timeout=1)
645
-
645
+
646
646
  # Verify task was processed
647
647
  assert executed, "Task execution timed out"
648
648
  finally:
@@ -662,13 +662,13 @@ class TestRedisTaskQueue:
662
662
  # Create a valid queue key first
663
663
  name = "test_queue"
664
664
  queue_key = task_queue._queue_key(name)
665
-
665
+
666
666
  # Extract the name back
667
667
  extracted_name = task_queue._queue_name(queue_key)
668
-
668
+
669
669
  # Verify extraction works
670
670
  assert extracted_name == name
671
-
671
+
672
672
  # Test with invalid queue key
673
673
  with pytest.raises(AssertionError):
674
674
  task_queue._queue_name("invalid_key")
@@ -677,10 +677,10 @@ class TestRedisTaskQueue:
677
677
  """Test getting a task that doesn't exist."""
678
678
  # Try to get a task with an ID that doesn't exist
679
679
  result = task_queue.get_task("nonexistent_task")
680
-
680
+
681
681
  # Verify that None is returned
682
682
  assert result is None
683
-
683
+
684
684
  # Try with once=True
685
685
  result = task_queue.get_task("nonexistent_task", once=True)
686
686
  assert result is None
@@ -689,13 +689,13 @@ class TestRedisTaskQueue:
689
689
  """Test execute_task_remotely when task has error attribute set."""
690
690
  # Create a task
691
691
  task = task_queue.build_task("error_task", "test", {"param": "value"})
692
-
692
+
693
693
  # Create a error for the task
694
694
  task_error = ValueError("Task error")
695
-
695
+
696
696
  # Mock time.sleep to avoid actual waiting
697
697
  mocker.patch('time.sleep')
698
-
698
+
699
699
  # Mock get_task to return a task with error attribute set
700
700
  def mock_get_task(task_id, once=False):
701
701
  task = RedisTask(
@@ -707,9 +707,9 @@ class TestRedisTaskQueue:
707
707
  _save=lambda: None
708
708
  )
709
709
  return task
710
-
710
+
711
711
  mocker.patch.object(task_queue, 'get_task', side_effect=mock_get_task)
712
-
712
+
713
713
  # Execute the task and expect the error to be raised
714
714
  with pytest.raises(ValueError, match="Task error"):
715
715
  task_queue.execute_task_remotely(task)
@@ -719,38 +719,38 @@ class TestRedisTaskQueue:
719
719
  # Create a task
720
720
  task = task_queue.build_task("timeout_task", "test", {"param": "value"})
721
721
  task_queue.interval = 0.5 # Set interval to 0.5 seconds for testing
722
-
722
+
723
723
  # Mock get_task to always return None (simulating no worker processing the task)
724
724
  mocker.patch.object(task_queue, 'get_task', return_value=None)
725
-
725
+
726
726
  # Mock time.sleep to count calls and track timeout reduction
727
727
  sleep_call_count = 0
728
728
  interval_sum = 0
729
-
729
+
730
730
  def mock_sleep(seconds):
731
731
  nonlocal sleep_call_count, interval_sum
732
732
  sleep_call_count += 1
733
733
  interval_sum += seconds
734
734
  # Don't actually sleep
735
-
735
+
736
736
  mocker.patch('time.sleep', side_effect=mock_sleep)
737
-
737
+
738
738
  # Set a small timeout to make the test fast
739
739
  timeout = 2.0 # Should allow for exactly 4 iterations with interval=0.5
740
-
740
+
741
741
  # Execute the task remotely with timeout and expect TimeoutError
742
742
  with pytest.raises(TimeoutError) as exc_info:
743
743
  task_queue.execute_task_remotely(task, timeout=timeout)
744
-
744
+
745
745
  # Verify error message
746
746
  assert f"Task {task.id} in {task.name} has expired" in str(exc_info.value)
747
-
747
+
748
748
  # Verify sleep was called
749
749
  # In the implementation, the loop continues while timeout >= 0, so we get 5 iterations
750
750
  # with timeout=2.0 and interval=0.5: [2.0, 1.5, 1.0, 0.5, 0.0]
751
751
  expected_calls = int(timeout / task_queue.interval) + 1 # +1 for the last iteration when timeout=0
752
752
  assert sleep_call_count == expected_calls
753
-
753
+
754
754
  # Verify that the total time slept approximately equals the timeout
755
755
  assert abs(interval_sum - timeout) <= task_queue.interval
756
756
 
@@ -758,21 +758,21 @@ class TestRedisTaskQueue:
758
758
  """Test execute_task_remotely method's timeout logic directly."""
759
759
  # Create a task
760
760
  task = task_queue.build_task("timeout_task2", "test", {"param": "value"})
761
-
761
+
762
762
  # Mock redis and get_task to simulate the behavior
763
763
  mocker.patch.object(task_queue, 'get_task', return_value=None)
764
-
764
+
765
765
  # Mock time.sleep to avoid actual waiting
766
766
  mocker.patch('time.sleep')
767
-
767
+
768
768
  # Force timeout to be exactly 0 after one iteration
769
769
  # This will trigger the exact lines we want to test
770
770
  task_queue.interval = 1.0
771
771
  timeout = 1.0 # Will become 0 after one iteration, then -1 after another
772
-
772
+
773
773
  # Execute task and expect timeout
774
774
  with pytest.raises(TimeoutError) as exc_info:
775
775
  task_queue.execute_task_remotely(task, timeout=timeout)
776
-
776
+
777
777
  # Verify timeout error
778
- assert str(exc_info.value) == f"Task {task.id} in {task.name} has expired"
778
+ assert str(exc_info.value) == f"Task {task.id} in {task.name} has expired"