Skip to content

Commit 4642deb

Browse files
committed
Queue notification to optimize polling
1 parent b1d0db4 commit 4642deb

3 files changed

Lines changed: 48 additions & 7 deletions

File tree

tasktiger/task.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,8 @@ def _move(self, from_state=None, to_state=None, when=None, mode=None):
320320
_key(from_state), queue, _key(from_state, queue), client=pipeline
321321
)
322322

323-
if to_state == QUEUED and self.tiger.config["PUBLISH_QUEUED_TASKS"]:
324-
pipeline.publish(_key("activity"), queue)
323+
if to_state == QUEUED:
324+
self.tiger._notify_queue(queue, client=pipeline)
325325

326326
try:
327327
scripts.execute_pipeline(pipeline)
@@ -396,8 +396,10 @@ def delay(self, when=None, max_queue_size=None):
396396
mode="nx",
397397
client=pipeline,
398398
)
399-
if state == QUEUED and tiger.config["PUBLISH_QUEUED_TASKS"]:
400-
pipeline.publish(tiger._key("activity"), self.queue)
399+
400+
if state == QUEUED:
401+
tiger._notify_queue(self.queue, client=pipeline)
402+
401403
pipeline.execute()
402404

403405
self._state = state

tasktiger/tasktiger.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import datetime
44
import importlib
55
import logging
6+
import secrets
67
from collections import defaultdict
78

89
import click
@@ -256,6 +257,20 @@ def _get_current_tasks(self):
256257
current_task = property(_get_current_task)
257258
current_tasks = property(_get_current_tasks)
258259

260+
def _notify_queue(self, queue, client=None):
261+
client = client or self.connection
262+
263+
if self.config["PUBLISH_QUEUED_TASKS"]:
264+
client.publish(self._key("activity"), queue)
265+
266+
# XXX Maybe use each element from `dotted_parts` instead just the queue root?
267+
# Not sure about performance though.
268+
client.set(
269+
self._key("queue_token", queue.split(".", 1)[0]),
270+
secrets.token_hex(),
271+
ex=7200, # XXX Just for tests so we don't clutter Redis
272+
)
273+
259274
@classproperty
260275
def current_instance(self):
261276
"""

tasktiger/worker.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def __init__(
6565
self._key = tiger._key
6666
self._did_work = True
6767
self._last_task_check = 0.0
68+
self._queue_set_token = ""
6869
self.stats_thread = None
6970
self.id = str(uuid.uuid4())
7071

@@ -200,8 +201,7 @@ def _worker_queue_scheduled_tasks(self) -> None:
200201
# XXX: ideally this would be in the same pipeline, but we only want
201202
# to announce if there was a result.
202203
if result:
203-
if self.config["PUBLISH_QUEUED_TASKS"]:
204-
self.connection.publish(self._key("activity"), queue)
204+
self.tiger._notify_queue(queue)
205205
self._did_work = True
206206

207207
def _poll_for_queues(self) -> None:
@@ -214,7 +214,31 @@ def _poll_for_queues(self) -> None:
214214
"""
215215
if not self._did_work:
216216
time.sleep(self.config["POLL_TASK_QUEUES_INTERVAL"])
217-
self._refresh_queue_set()
217+
218+
if self._is_queue_set_out_of_date():
219+
self._refresh_queue_set()
220+
self.log.info(f"Poll: Done ({len(self._queue_set)})")
221+
222+
def _is_queue_set_out_of_date(self) -> bool:
223+
if not self.only_queues:
224+
return True
225+
226+
queue_set_token = ":".join(
227+
token or ""
228+
for token in self.connection.mget(
229+
sorted(
230+
self._key("queue_token", queue)
231+
for queue in self.only_queues
232+
)
233+
)
234+
)
235+
236+
if queue_set_token != self._queue_set_token:
237+
self.log.info("Poll: Token changed")
238+
self._queue_set_token = queue_set_token
239+
return True
240+
241+
return False
218242

219243
def _pubsub_for_queues(self, timeout=0, batch_timeout=0) -> None:
220244
"""

0 commit comments

Comments
 (0)