mirror of
https://github.com/gadgethd/ukmesh.git
synced 2026-09-04 06:13:44 +00:00
138 lines
5.1 KiB
Python
138 lines
5.1 KiB
Python
import os
|
|
import random
|
|
import unittest
|
|
|
|
import redis
|
|
|
|
import link_queue_v3 as queue
|
|
|
|
|
|
@unittest.skipUnless(os.environ.get('TEST_REDIS_URL'), 'TEST_REDIS_URL is required')
|
|
class LinkQueueV3RedisTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.redis = redis.Redis.from_url(
|
|
os.environ['TEST_REDIS_URL'],
|
|
password=os.environ.get('TEST_REDIS_PASSWORD') or None,
|
|
decode_responses=True,
|
|
)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
cls.redis.close()
|
|
|
|
def setUp(self):
|
|
self.redis.flushdb()
|
|
|
|
def _admit(self, index: int):
|
|
job_id = f'job-{index}'
|
|
status, accepted_id = queue.admit(self.redis, {
|
|
'version': 3,
|
|
'type': 'physical_pair',
|
|
'job_id': job_id,
|
|
'dedupe_key': f'pair-{index}',
|
|
'node_a_id': f'a-{index}',
|
|
'node_b_id': f'b-{index}',
|
|
})
|
|
self.assertEqual((status, accepted_id), ('accepted', job_id))
|
|
self.assertEqual(self.redis.llen(queue.WAKE), 1)
|
|
return job_id
|
|
|
|
def test_final_nack_releases_active_capacity_and_retains_purgeable_dead_payload(self):
|
|
job_id = self._admit(1)
|
|
for attempt in range(queue.MAX_ATTEMPTS):
|
|
claimed = queue.claim(self.redis)
|
|
self.assertIsNotNone(claimed)
|
|
claimed_id, token, _payload, actual_attempt = claimed
|
|
self.assertEqual(claimed_id, job_id)
|
|
self.assertEqual(actual_attempt, attempt + 1)
|
|
transition = queue.nack(self.redis, job_id, token)
|
|
|
|
self.assertEqual(transition, 'dead')
|
|
report = queue.audit_invariants(self.redis)
|
|
self.assertEqual(report['actual_count'], 0)
|
|
self.assertEqual(report['actual_dead_count'], 1)
|
|
self.assertGreater(report['actual_dead_bytes'], 0)
|
|
self.assertTrue(report['consistent'])
|
|
self.assertEqual(
|
|
self.redis.hget(queue.DEAD_REASONS, job_id),
|
|
'attempt_limit_exceeded',
|
|
)
|
|
|
|
self.assertTrue(queue.purge_dead(self.redis, job_id))
|
|
report = queue.audit_invariants(self.redis)
|
|
self.assertEqual(report['actual_dead_count'], 0)
|
|
self.assertEqual(self.redis.hexists(queue.PAYLOADS, job_id), 0)
|
|
self.assertEqual(self.redis.hexists(queue.DEDUPE_BY_JOB, job_id), 0)
|
|
self.assertEqual(self.redis.hexists(queue.DEAD_REASONS, job_id), 0)
|
|
|
|
def test_requeue_dead_moves_accounting_back_under_active_admission_limits(self):
|
|
job_id = self._admit(2)
|
|
for _ in range(queue.MAX_ATTEMPTS):
|
|
claimed_id, token, _payload, _attempt = queue.claim(self.redis)
|
|
self.assertEqual(claimed_id, job_id)
|
|
queue.nack(self.redis, job_id, token)
|
|
|
|
self.assertEqual(queue.requeue_dead(self.redis, job_id), 'requeued')
|
|
self.assertEqual(self.redis.hexists(queue.DEAD_REASONS, job_id), 0)
|
|
report = queue.audit_invariants(self.redis)
|
|
self.assertEqual(report['actual_count'], 1)
|
|
self.assertEqual(report['actual_dead_count'], 0)
|
|
self.assertTrue(report['consistent'])
|
|
|
|
def test_atomic_repair_reconstructs_corrupt_counters_from_bounded_job_state(self):
|
|
self._admit(3)
|
|
self._admit(4)
|
|
self.redis.hset(queue.COUNTERS, mapping={
|
|
'count': 99,
|
|
'bytes': 1,
|
|
'dead_count': 12,
|
|
'dead_bytes': 34,
|
|
})
|
|
|
|
before = queue.audit_invariants(self.redis)
|
|
self.assertFalse(before['consistent'])
|
|
self.assertEqual(before['actual_count'], 2)
|
|
repaired = queue.audit_invariants(self.redis, apply=True)
|
|
self.assertTrue(repaired['applied'])
|
|
self.assertTrue(queue.audit_invariants(self.redis)['consistent'])
|
|
|
|
def test_randomized_transitions_preserve_recorded_count_and_byte_invariants(self):
|
|
rng = random.Random(20260729)
|
|
next_job = 0
|
|
for _ in range(500):
|
|
action = rng.randrange(6)
|
|
if action <= 1:
|
|
next_job += 1
|
|
queue.admit(self.redis, {
|
|
'version': 3,
|
|
'type': 'physical_pair',
|
|
'job_id': f'random-{next_job}',
|
|
'dedupe_key': f'random-pair-{next_job}',
|
|
'node_a_id': f'a-{next_job}',
|
|
'node_b_id': f'b-{next_job}',
|
|
})
|
|
elif action in (2, 3):
|
|
claimed = queue.claim(self.redis)
|
|
if claimed:
|
|
job_id, token, _payload, _attempt = claimed
|
|
if action == 2:
|
|
queue.ack(self.redis, job_id, token)
|
|
else:
|
|
queue.nack(self.redis, job_id, token)
|
|
elif action == 4:
|
|
dead = self.redis.zrange(queue.DEAD, 0, 0)
|
|
if dead:
|
|
queue.requeue_dead(self.redis, dead[0])
|
|
else:
|
|
dead = self.redis.zrange(queue.DEAD, 0, 0)
|
|
if dead:
|
|
queue.purge_dead(self.redis, dead[0])
|
|
|
|
report = queue.audit_invariants(self.redis)
|
|
self.assertTrue(report['consistent'], report)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|