MCPcopy Create free account
hub / github.com/Dispatcharr/Dispatcharr / TaskLockRenewer

Class TaskLockRenewer

core/utils.py:323–388  ·  view source on GitHub ↗

Periodically renews a Redis task lock to prevent expiry during long-running tasks. Use as a context manager after acquiring a lock: if acquire_task_lock("my_task", task_id): with TaskLockRenewer("my_task", task_id): # ... long-running work ... re

Source from the content-addressed store, hash-verified

321
322
323class TaskLockRenewer:
324 """Periodically renews a Redis task lock to prevent expiry during long-running tasks.
325
326 Use as a context manager after acquiring a lock:
327
328 if acquire_task_lock("my_task", task_id):
329 with TaskLockRenewer("my_task", task_id):
330 # ... long-running work ...
331 release_task_lock("my_task", task_id)
332
333 A daemon thread extends the lock TTL at regular intervals so that
334 slow downloads or large parsing jobs don't lose their lock mid-operation.
335 """
336
337 def __init__(self, task_name, id, ttl=300, renewal_interval=120):
338 self.task_name = task_name
339 self.id = id
340 self.ttl = ttl
341 self.renewal_interval = renewal_interval
342 self.lock_id = f"task_lock_{task_name}_{id}"
343 self._stop_event = threading.Event()
344 self._thread = None
345
346 def _renew_loop(self):
347 """Background loop that extends the lock TTL until stopped."""
348 while not self._stop_event.wait(self.renewal_interval):
349 try:
350 redis_client = RedisClient.get_client()
351 if redis_client.exists(self.lock_id):
352 redis_client.expire(self.lock_id, self.ttl)
353 logger.debug(
354 f"Renewed lock {self.lock_id} TTL to {self.ttl}s"
355 )
356 else:
357 # Lock was deleted externally (e.g. manual release) — stop renewing
358 logger.warning(
359 f"Lock {self.lock_id} no longer exists, stopping renewal"
360 )
361 break
362 except Exception as e:
363 logger.error(f"Error renewing lock {self.lock_id}: {e}")
364
365 def start(self):
366 """Start the background renewal thread."""
367 self._stop_event.clear()
368 self._thread = threading.Thread(
369 target=self._renew_loop, daemon=True,
370 name=f"lock-renew-{self.task_name}-{self.id}"
371 )
372 self._thread.start()
373 return self
374
375 def stop(self):
376 """Stop the renewal thread."""
377 self._stop_event.set()
378 if self._thread and self._thread.is_alive():
379 self._thread.join(timeout=5)
380 self._thread = None

Callers 6

refresh_m3u_groupsFunction · 0.90
refresh_epg_dataFunction · 0.90
fetch_sd_guide_for_epgFunction · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected