move command to package

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Marc 'risson' Schmitt
2025-06-19 14:25:18 +02:00
parent 2ca9edb1bc
commit 8980282a02
11 changed files with 144 additions and 113 deletions

View File

@ -303,7 +303,6 @@ class _PostgresConsumer(Consumer):
def _poll_for_notify(self):
with self.listen_connection.cursor() as cursor:
self.logger.debug(f"timeout is {self.timeout}")
notifies = list(cursor.connection.notifies(timeout=self.timeout, stop_after=1))
self.logger.debug(
f"Received {len(notifies)} postgres notifies on channel {self.postgres_channel}"

View File

@ -7,12 +7,16 @@ from django.core.exceptions import ImproperlyConfigured
class Conf:
def __init__(self):
try:
self.conf = settings.DRAMATIQ
_ = settings.DRAMATIQ
except AttributeError as exc:
raise ImproperlyConfigured("Setting DRAMATIQ not set.") from exc
if "task_class" not in self.conf:
raise ImproperlyConfigured("DRAMATIQ.task_class not defined")
@property
def conf(self) -> dict[str, Any]:
return settings.DRAMATIQ
@property
def encoder_class(self) -> str:
return self.conf.get("encoder_class", "dramatiq.encoder.PickleEncoder")
@ -52,6 +56,34 @@ class Conf:
def task_class(self) -> str:
return self.conf["task_class"]
@property
def autodiscovery(self) -> dict[str, Any]:
autodiscovery = {
"enabled": False,
"setup_module": "django_dramatiq_postgres.setup",
"apps_prefix": None,
"actors_module_name": "tasks",
"modules_callback": None,
**self.conf.get("autodiscovery", {}),
}
if not autodiscovery["enabled"] and not autodiscovery["modules_callback"]:
raise ImproperlyConfigured(
"One of DRAMATIQ.autodiscovery.enabled or "
"DRAMATIQ.autodiscovery.modules_callback must be configured."
)
return autodiscovery
@property
def worker(self) -> dict[str, Any]:
return {
"use_gevent": False,
"watch": settings.DEBUG,
"watch_use_polling": False,
"processes": None,
"threads": None,
**self.conf.get("worker", {}),
}
@property
def test(self) -> bool:
return self.conf.get("test", False)

View File

@ -0,0 +1,92 @@
import os
import sys
from django.apps.registry import apps
from django.core.management.base import BaseCommand
from django.utils.module_loading import import_string, module_has_submodule
from django_dramatiq_postgres.conf import Conf
class Command(BaseCommand):
"""Run worker"""
def add_arguments(self, parser):
parser.add_argument(
"--pid-file",
action="store",
default=None,
dest="pid_file",
help="PID file",
)
def handle(
self,
pid_file,
verbosity,
**options,
):
worker = Conf().worker
executable_name = "dramatiq-gevent" if worker["use_gevent"] else "dramatiq"
executable_path = self._resolve_executable(executable_name)
watch_args = ["--watch", "."] if worker["watch"] else []
if watch_args and worker["watch_use_polling"]:
watch_args.append("--watch-use-polling")
parallel_args = []
if processes := worker["processes"]:
parallel_args.extend(["--processes", str(processes)])
if threads := worker["threads"]:
parallel_args.extend(["--threads", str(threads)])
pid_file_args = []
if pid_file is not None:
pid_file_args = ["--pid-file", pid_file]
verbosity_args = ["-v"] * (verbosity - 1)
tasks_modules = self._discover_tasks_modules()
process_args = [
executable_name,
"--path",
".",
*parallel_args,
*watch_args,
*pid_file_args,
*verbosity_args,
*tasks_modules,
]
os.execvp(executable_path, process_args) # nosec
def _resolve_executable(self, exec_name: str):
bin_dir = os.path.dirname(sys.executable)
if bin_dir:
for d in [bin_dir, os.path.join(bin_dir, "Scripts")]:
exec_path = os.path.join(d, exec_name)
if os.path.isfile(exec_path):
return exec_path
return exec_name
def _discover_tasks_modules(self) -> list[str]:
# Does not support a tasks directory
autodiscovery = Conf().autodiscovery
modules = [autodiscovery["setup_module"]]
if autodiscovery["enabled"]:
for app in apps.get_app_configs():
if autodiscovery["apps_prefix"] and not app.name.startswith(
autodiscovery["apps_prefix"]
):
continue
if module_has_submodule(app.module, autodiscovery["actors_module_name"]):
modules.append(f"{app.name}.{autodiscovery['actors_module_name']}")
else:
modules_callback = autodiscovery["modules_callback"]
callback = (
modules_callback
if not isinstance(modules_callback, str)
else import_string(modules_callback)
)
modules.extend(callback())
return modules

View File

@ -0,0 +1,3 @@
import django
django.setup()