11from __future__ import annotations
22
33import asyncio
4- from collections import abc
54from dataclasses import dataclass
65from typing import TYPE_CHECKING , Any
76
8- import saq
7+ from saq import Job as SaqJob
8+ from saq import Worker as SaqWorker
9+ from saq .job import CronJob as SaqCronJob
10+ from saq .queue import Queue as SaqQueue
911
1012if TYPE_CHECKING :
13+ from collections .abc import Collection
1114 from signal import Signals
1215
13-
14- WorkerFunction = abc . Callable [..., abc . Awaitable [ Any ]]
16+ from redis . asyncio . client import Redis
17+ from saq . types import DumpType , Function , LoadType , PartialTimersDict , ReceivesContext
1518
1619
1720@dataclass
18- class Job (saq . Job ):
21+ class Job (SaqJob ):
1922 """Job Details"""
2023
2124 job_name : str | None = None
2225 job_description : str | None = None
2326
2427
2528@dataclass
26- class CronJob (saq . CronJob ):
29+ class CronJob (SaqCronJob ):
2730 """Cron Job Details"""
2831
2932 job_name : str | None = None
3033 job_description : str | None = None
3134
3235
33- class BackgroundTaskError (Exception ):
34- """Base class for `Task` related exceptions."""
35-
36-
37- class Queue (saq .Queue ):
36+ class Queue (SaqQueue ):
3837 """[SAQ Queue](https://github.com/tobymao/saq/blob/master/saq/queue.py).
3938
4039 Configures `msgspec` for msgpack serialization/deserialization if not otherwise configured.
@@ -47,22 +46,72 @@ class Queue(saq.Queue):
4746 Passed through to `saq.Queue.__init__()`
4847 """
4948
50- def __init__ (self , * args : Any , ** kwargs : Any ) -> None :
49+ def __init__ (
50+ self ,
51+ redis : Redis [bytes ],
52+ name : str = "default" ,
53+ dump : DumpType | None = None ,
54+ load : LoadType | None = None ,
55+ max_concurrent_ops : int = 20 ,
56+ queue_namespace : str | None = None ,
57+ ) -> None :
58+ self ._namespace = queue_namespace if queue_namespace is not None else "saq"
59+ super ().__init__ (redis , name , dump , load , max_concurrent_ops )
60+
61+ def temp (self , * args : Any , ** kwargs : Any ) -> None :
5162 """Initialize a new queue."""
52- """
53- kwargs.setdefault("dump", serialization.to_json)
54- kwargs.setdefault("load", serialization.from_json)
55- kwargs.setdefault("name", "background-tasks")
56- """
63+ self ._namespace = kwargs .pop ("queue_namespace" , "saq" )
5764 super ().__init__ (* args , ** kwargs )
5865
66+ def namespace (self , key : str ) -> str :
67+ """Make the namespace unique per app."""
68+ return f"{ self ._namespace } :{ self .name } :{ key } "
69+
70+ def job_id (self , job_key : str ) -> str :
71+ """Job ID.
5972
60- class Worker (saq .Worker ):
73+ Args:
74+ job_key (str): Sets the job ID for the given key
75+
76+ Returns:
77+ str: Job ID for the specified key
78+ """
79+ return f"{ self ._namespace } :{ self .name } :job:{ job_key } "
80+
81+
82+ class Worker (SaqWorker ):
6183 """Worker."""
6284
6385 # same issue: https://github.com/samuelcolvin/arq/issues/182
6486 SIGNALS : list [Signals ] = []
6587
88+ def __init__ (
89+ self ,
90+ queue : Queue | SaqQueue ,
91+ functions : Collection [Function | tuple [str , Function ]],
92+ * ,
93+ concurrency : int = 10 ,
94+ cron_jobs : Collection [CronJob ] | None = None ,
95+ startup : ReceivesContext | None = None ,
96+ shutdown : ReceivesContext | None = None ,
97+ before_process : ReceivesContext | None = None ,
98+ after_process : ReceivesContext | None = None ,
99+ timers : PartialTimersDict | None = None ,
100+ dequeue_timeout : float = 0 ,
101+ ) -> None :
102+ super ().__init__ (
103+ queue ,
104+ functions ,
105+ concurrency = concurrency ,
106+ cron_jobs = cron_jobs ,
107+ startup = startup ,
108+ shutdown = shutdown ,
109+ before_process = before_process ,
110+ after_process = after_process ,
111+ timers = timers ,
112+ dequeue_timeout = dequeue_timeout ,
113+ )
114+
66115 async def on_app_startup (self ) -> None :
67116 """Attach the worker to the running event loop."""
68117 loop = asyncio .get_running_loop ()
0 commit comments