# Documented in https://zulip.readthedocs.io/en/latest/subsystems/queuing.html import logging import time from collections.abc import Mapping, Sequence from typing import Any import orjson from django.conf import settings from typing_extensions import override from zerver.worker.base import LoopQueueProcessingWorker, QueueProcessingWorker, assign_queue logger = logging.getLogger(__name__) @assign_queue("test", is_test_queue=True) class TestWorker(QueueProcessingWorker): # This worker allows you to test the queue worker infrastructure without # creating significant side effects. It can be useful in development or # for troubleshooting prod/staging. It pulls a message off the test queue # and appends it to a file in /var/log/zulip. @override def consume(self, event: Mapping[str, Any]) -> None: # nocoverage fn = settings.ZULIP_WORKER_TEST_FILE message = orjson.dumps(event) logging.info("TestWorker should append this message to %s: %s", fn, message.decode()) with open(fn, "ab") as f: f.write(message + b"\n") @assign_queue("noop", is_test_queue=True) class NoopWorker(QueueProcessingWorker): """Used to profile the queue processing framework, in zilencer's queue_rate.""" def __init__( self, threaded: bool = False, disable_timeout: bool = False, worker_num: int | None = None, max_consume: int = 1000, slow_queries: Sequence[int] = [], ) -> None: super().__init__(threaded, disable_timeout, worker_num) self.consumed = 0 self.max_consume = max_consume self.slow_queries: set[int] = set(slow_queries) @override def consume(self, event: Mapping[str, Any]) -> None: self.consumed += 1 if self.consumed in self.slow_queries: logging.info("Slow request...") time.sleep(60) logging.info("Done!") if self.consumed >= self.max_consume: self.stop() @assign_queue("noop_batch", is_test_queue=True) class BatchNoopWorker(LoopQueueProcessingWorker): """Used to profile the queue processing framework, in zilencer's queue_rate.""" batch_size = 100 def __init__( self, threaded: bool = False, disable_timeout: bool = False, max_consume: int = 1000, slow_queries: Sequence[int] = [], ) -> None: super().__init__(threaded, disable_timeout) self.consumed = 0 self.max_consume = max_consume self.slow_queries: set[int] = set(slow_queries) @override def consume_batch(self, events: list[dict[str, Any]]) -> None: event_numbers = set(range(self.consumed + 1, self.consumed + 1 + len(events))) found_slow = self.slow_queries & event_numbers if found_slow: logging.info("%d slow requests...", len(found_slow)) time.sleep(60 * len(found_slow)) logging.info("Done!") self.consumed += len(events) if self.consumed >= self.max_consume: self.stop()