Add a task counter to cluster task scheduler
PYTHON-473 Fixes a TypeError when tasks collide in time and function comparison is attempted (Python 3 only). https://docs.python.org/2/library/heapq.html#priority-queue-implementation-notes
This commit is contained in:
@@ -41,7 +41,7 @@ except ImportError:
|
||||
from cassandra.util import WeakSet # NOQA
|
||||
|
||||
from functools import partial, wraps
|
||||
from itertools import groupby
|
||||
from itertools import groupby, count
|
||||
|
||||
from cassandra import (ConsistencyLevel, AuthenticationFailed,
|
||||
OperationTimedOut, UnsupportedOperation,
|
||||
@@ -2542,6 +2542,7 @@ class _Scheduler(object):
|
||||
def __init__(self, executor):
|
||||
self._queue = Queue.PriorityQueue()
|
||||
self._scheduled_tasks = set()
|
||||
self._count = count()
|
||||
self._executor = executor
|
||||
|
||||
t = Thread(target=self.run, name="Task Scheduler")
|
||||
@@ -2559,7 +2560,7 @@ class _Scheduler(object):
|
||||
# this can happen on interpreter shutdown
|
||||
pass
|
||||
self.is_shutdown = True
|
||||
self._queue.put_nowait((0, None))
|
||||
self._queue.put_nowait((0, 0, None))
|
||||
|
||||
def schedule(self, delay, fn, *args, **kwargs):
|
||||
self._insert_task(delay, (fn, args, tuple(kwargs.items())))
|
||||
@@ -2575,7 +2576,7 @@ class _Scheduler(object):
|
||||
if not self.is_shutdown:
|
||||
run_at = time.time() + delay
|
||||
self._scheduled_tasks.add(task)
|
||||
self._queue.put_nowait((run_at, task))
|
||||
self._queue.put_nowait((run_at, next(self._count), task))
|
||||
else:
|
||||
log.debug("Ignoring scheduled task after shutdown: %r", task)
|
||||
|
||||
@@ -2586,7 +2587,7 @@ class _Scheduler(object):
|
||||
|
||||
try:
|
||||
while True:
|
||||
run_at, task = self._queue.get(block=True, timeout=None)
|
||||
run_at, i, task = self._queue.get(block=True, timeout=None)
|
||||
if self.is_shutdown:
|
||||
log.debug("Not executing scheduled task due to Scheduler shutdown")
|
||||
return
|
||||
@@ -2597,7 +2598,7 @@ class _Scheduler(object):
|
||||
future = self._executor.submit(fn, *args, **kwargs)
|
||||
future.add_done_callback(self._log_if_failed)
|
||||
else:
|
||||
self._queue.put_nowait((run_at, task))
|
||||
self._queue.put_nowait((run_at, i, task))
|
||||
break
|
||||
except Queue.Empty:
|
||||
pass
|
||||
|
||||
@@ -419,19 +419,13 @@ class TimerTest(unittest.TestCase):
|
||||
|
||||
def test_timer_collision(self):
|
||||
# simple test demonstrating #466
|
||||
def f1():
|
||||
pass
|
||||
|
||||
def f2():
|
||||
pass
|
||||
|
||||
# same timeout, comparison will defer to the Timer object itself
|
||||
t1 = Timer(0, f1)
|
||||
t2 = Timer(0, f2)
|
||||
t1 = Timer(0, lambda: None)
|
||||
t2 = Timer(0, lambda: None)
|
||||
t2.end = t1.end
|
||||
|
||||
tm = TimerManager()
|
||||
tm.add_timer(t1)
|
||||
tm.add_timer(t2)
|
||||
# Prior to $466: "TypeError: unorderable types: Timer() < Timer()"
|
||||
# Prior to #466: "TypeError: unorderable types: Timer() < Timer()"
|
||||
tm.service_timeouts()
|
||||
|
||||
Reference in New Issue
Block a user