API 参考#
binomic.client#
- class binomic.client.Binomic(broker_dsn: str, module_name: str, config: BinomicConfig)#
Binomic working client.
Entering the async context starts the master process group and keeps it running until the context exits.
- async submit(msg: Message) UUID#
Dispatch a message to its task.
directtasks are enqueued immediately anddelaytasks are handed to the scheduler for a deferred enqueue. Scheduled tasks (cronandinterval) cannot be submitted: they are registered automatically when the client starts.- Raises:
TaskNotFoundError: if no task is registered under the message's name. RuntimeError: if the client has not been started with
arun. ValueError: if the task's mode is neitherdirectnordelay.
- class binomic.client.BinomicFactory(broker_dsn: str, module_name: str, config: BinomicConfig)#
Binomic working client factory.
binomic.config#
- class binomic.config.BinomicConfig(queues: list[str], workers: int = 1, concurrency: int = 5, max_attempts: int = 3)#
Binomic configuration.
workersis the number of worker subprocesses the master spawns andconcurrencythe number of tasks each worker executes concurrently; every stream inqueuesis consumed by all workers.max_attemptsis how many times a message may be delivered before it is dropped.
binomic.task#
- exception binomic.task.DuplicateTaskError#
Duplicate task error.
- exception binomic.task.TaskNotFoundError#
Task not found error.
- class binomic.task.TaskScheduler(timezone: tzinfo = datetime.timezone.utc)#
Scheduler class for Binomic tasks.
- cron(func: Callable[[...], Any | Awaitable[Any]], spec: TaskSpec, *, args: Sequence[Any] | None = None, kwargs: Mapping[str, Any] | None = None) None#
Schedule a task to run at specific times.
- delay(func: Callable[[...], Any | Awaitable[Any]], spec: TaskSpec, *, delay: float | None = None, args: Sequence[Any] | None = None, kwargs: Mapping[str, Any] | None = None) None#
Delay a task.
- interval(func: Callable[[...], Any | Awaitable[Any]], spec: TaskSpec, *, args: Sequence[Any] | None = None, kwargs: Mapping[str, Any] | None = None) None#
Schedule a task to run at regular intervals.
- shutdown() None#
Shutdown the scheduler.
- start() None#
Start the scheduler.
- class binomic.task.TaskSpec(name: str, queue: str, fn: Callable[[P], T], mode: Literal['direct', 'delay', 'cron', 'interval'] = 'direct', delay: float | None = None, cron: str | None = None, interval: float | None = None)#
- binomic.task.autodiscover(package: str, *, on_error: Literal['warn', 'raise'] = 'warn') list[str]#
Import every
tasksmodule inside package to trigger registration.Returns the names of the imported modules; a failing module import is warned or raised depending on
on_error.
- binomic.task.task(queue: str, *, mode: Literal['direct']) Callable[[Callable[P, T]], TaskSpec[P, T]]#
- binomic.task.task(queue: str, *, mode: Literal['delay'], delay: float) Callable[[Callable[P, T]], TaskSpec[P, T]]
- binomic.task.task(queue: str, *, mode: Literal['cron'], cron: str) Callable[[Callable[P, T]], TaskSpec[P, T]]
- binomic.task.task(queue: str, *, mode: Literal['interval'], interval: float) Callable[[Callable[P, T]], TaskSpec[P, T]]
Declare a task and register it under the function's lowercase name.
Mode
directexecutes on submit,delayschedules executiondelayseconds after submit,cronrepeats execution on the given cron expression, andintervalrepeats it everyintervalseconds.- Raises:
- ValueError: if
delay,cronorintervalmode lacks its required argument, or if a
cronorintervaltask's function takes parameters.
- ValueError: if
binomic.task.scheduler#
- class binomic.task.scheduler.TaskScheduler(timezone: tzinfo = datetime.timezone.utc)#
Scheduler class for Binomic tasks.
- cron(func: Callable[[...], Any | Awaitable[Any]], spec: TaskSpec, *, args: Sequence[Any] | None = None, kwargs: Mapping[str, Any] | None = None) None#
Schedule a task to run at specific times.
- delay(func: Callable[[...], Any | Awaitable[Any]], spec: TaskSpec, *, delay: float | None = None, args: Sequence[Any] | None = None, kwargs: Mapping[str, Any] | None = None) None#
Delay a task.
- interval(func: Callable[[...], Any | Awaitable[Any]], spec: TaskSpec, *, args: Sequence[Any] | None = None, kwargs: Mapping[str, Any] | None = None) None#
Schedule a task to run at regular intervals.
- shutdown() None#
Shutdown the scheduler.
- start() None#
Start the scheduler.
binomic.message#
- class binomic.message.Message(name: str, id: UUID = <factory>, attempt: int = 1, args: list[Any] = <factory>, kwargs: dict[str, ~typing.Any]=<factory>)#
Message for binomic.
nameis the registered task name andargs/kwargscarry the task call arguments. The delivery timestamp is not carried here: the broker stamps it on the stream entry when the message is enqueued.- to_json() str#
Convert the data structure to a JSON string.
binomic.broker#
- class binomic.broker.AsyncredisBroker(dsn: str, queues: Sequence[str], **config: Any)#
Broker based on async redis.
- get_stream_key(queue: str) str#
Namespace a queue name into its Redis stream key.
- class binomic.broker.Broker(*args, **kwargs)#
Broker protocol class.
- class binomic.broker.BrokerFactory(dsn: str, queues: list[str])#
A factory class for creating broker instances.
binomic.worker#
- class binomic.worker.Master(*, broker_dsn: str, module_name: str, policy: MasterPolicy)#
Binomic processing visor.
- class binomic.worker.MasterPolicy(workers: int, worker: WorkerPolicy)#
Binomic master policy.
- class binomic.worker.MasterPresence#
Master-side view of the liveness of every worker.
One instance covers the whole worker set, the way the map it replaced did:
presence()returns every watched worker's last beat. Comparing that map against the clock is how the visor tells a worker that is stuck apart from one that is merely idle:is_alivestays true while a stalled worker stops writing.- presence() dict[str, float]#
The last beat of every watched worker.
Each cell is read through its object, without taking its lock: the lock exists for read-modify-write sequences and nothing here does one. Taking it would mean waiting on a worker that died -- or was stopped -- while holding it, which would wedge the visor for good.
- watch(ident: str, cell: Synchronized[float]) None#
Take over the cell a worker beats on, replacing any earlier one.
- class binomic.worker.SubprocessPresence(heartbeat: Synchronized[float])#
Subprocess-side view of a worker's liveness.
Borrows the cell the master created: the master owns it and frees it, so nothing here closes it.
- class binomic.worker.Worker(*, broker_dsn: str, module_name: str, consumer: str, policy: WorkerPolicy, presence: SubprocessPresence)#
Binomic subprocessing worker.
Spawned rather than forked: a forked child inherits the parent's running event loop, so
anyio.runcannot start in it.- run() None#
Method to be run in sub-process; can be overridden in sub-class
- class binomic.worker.WorkerPolicy(queues: list[str], concurrency: int, task_timeout: float = 600.0, max_attempts: int = 3, read_count: int = 10, poll_interval: float = 0.1, heartbeat_interval: float = 5.0, reclaim_interval: float = 30.0)#
Binomic worker policy.
binomic.base#
- class binomic.base.BaseStruct#
Base data structure.
- classmethod from_json(json_str: str) Self#
Create a data structure from a JSON string.
- to_json() str#
Convert the data structure to a JSON string.
- exception binomic.base.BinomicError#
Base class for binomic exceptions.
- exception binomic.base.DeserializationError#
Exception raised for errors during deserialization.
- exception binomic.base.SerializationError#
Exception raised for errors during serialization.
binomic.plugin.litestar#
- class binomic.plugin.litestar.BinomicPlugin(app_name: str, broker_dsn: str, config: BinomicConfig)#
Binomic plugin for litestar.
- on_app_init(app_config: AppConfig) AppConfig#
Receive the
AppConfiginstance after on_app_init hooks have been called.- Examples:
from litestar import Litestar, get from litestar.di import Provide from litestar.plugins import InitPluginProtocol def get_name() -> str: return "world" @get("/my-path") def my_route_handler(name: str) -> dict[str, str]: return {"hello": name} class MyPlugin(InitPluginProtocol): def on_app_init(self, app_config: AppConfig) -> AppConfig: app_config.dependencies["name"] = Provide(get_name) app_config.route_handlers.append(my_route_handler) return app_config app = Litestar(plugins=[MyPlugin()])
- Args:
app_config: The
AppConfiginstance.- Returns:
The app config object.