From 26d6ae4c9119211cad9c350807fa012a0ffb6119 Mon Sep 17 00:00:00 2001 From: <> Date: Thu, 21 Nov 2024 22:26:12 +0000 Subject: [PATCH] Deployed 2231e35 with MkDocs version: 1.6.1 --- objects.inv | Bin 2386 -> 2388 bytes reference/task_manager/index.html | 346 +++++++++++++-------------- reference/tast_consumer/index.html | 364 ++++++++++++++--------------- search/search_index.json | 2 +- 4 files changed, 346 insertions(+), 366 deletions(-) diff --git a/objects.inv b/objects.inv index 6fbddb4b451436db4e14039453bf2ad2d5c6bd49..3712647f140b4c7df370cd4be5cdd8ae5e6f604f 100644 GIT binary patch delta 2284 zcmV8Vi{)u=L4 zAKLEk$;)uThwp!Q`tiGq7jVjoN~<1oF=f`~RY@kPGJPpj(tkG*;a&2gRn5TDGQg&~ zC8jAvU{}=+){@4QqClPG<)soq7F8zmC`$E~nC`D4uz!p)Dk)TXZC?d}VsY1~Yp(mq zds(`e98=h3bMIkk+csp-aP81F)=0L$;o9-Zl<7@rwog-^(^l{?PlDQ{%<`&4m zZIVrw#385je1A^fs-{y6COQ=JCC!VZGOZkN=?$)1hC+3hUh=C9s!@=rpfY3G9mPH8 zx=!2fZ!&jLm3=}<^}WpcX03Xcd)Vq-Wu{fqyrefP2E8_ErY@!^?ul-zT8x|P{;`*N zd6h)=7HdgnX>R@HnQ6NA?PH$A4lEZqxm1m)^HsiM8-K3KM8BH$T)oM4)?w(9r6p!!=JV$1@soj{=)d3=@@#Y>ufl_w7qk8_^22cd6Oe~CO?bij$t<&dyj^{*12 zPe=}gtL)1DxjMZl(NS7Fljt^WTJaHOpqg5eH;(uGC(@COT;L6vt#0zF$=iD(o0bQ* zEV8}VGJm(xlm}<`ekAIL^+df34oPF)8Po#5yMMM@Z2vB(0f&sx7 z7zk>7d4Yf-7Z(_Ed})EFMHdzbBycu~AVxC`f`v~C6gX&FMh3?xWfXLLX9&p*ZLWb) z!EqJA35_cV3}sXS;J=Jn%#*6S92abQI-4dPlz+WH5R6D}nn6+JnbR7Q+M<-4V<9ge z^BF2aC+DhU5-w?8n1%z1A6@_u*K24ri~>Tl7+~{+^*HOaNm&6s0+O@2)ydzwDw%h5 zo`*9W4dKbTCt5XmTIByh&H@0iHd#_Mhtn^|I6o>pOhntyw}R1p&hi{g)usiZ{WwK; zo_}jU`;KP(M>`M!$GJB_X`(>%e5d0S)in#E?LA4Sh+8m_y6f1Tq&$Nls^0T?in0a6 zs5=hxIraERdRcAY+X|=tWZ$(*j_i)ii->OpPvP=7C; ziXf_u6%OIRSwO_Fu<)QBf(1uZBTgvC(XLWS(%AsVxZ9RFam--HbKgN0)x(+x^{_ws zqNt zI+Uo7+m;Iyl+yI!dveh7Q<@LLhFqv>m1qLC8y78bWvPR<;$j7{GzW-X1b_W3O&T=R zAqs72E@&eTutb+>3A{uG7xqdRf~}9^1;I=&kj1gLf|#QnUm3frjcJ;o3A(c^nWhJs z4Wi1IX*Lj3!7d(Eq4$N)&wtK>H($MUjJvOjM)4ob!9wfWX_{6~h{~;ttZ_1Z%Qzk~ zREK4}L-a-}r~Z%}@H=*;+(?PiyR_R1Z3@1TI#X+i%(f~VtuzCoV)62~pp>WZZ6{*Y zmt!TaS3q_-g_d*?3C{}7A&`(Gd2St**_5*5RHnv25l^{0MRJ9Ti+^v6R_q zrFHjQl6gKa3STDHv458hsRFCHyOhMoR4b_vv01VYa>EvVjvMyD_xOmXDD?!7=-)?0 z#8J_3WF#CA1>-5km@2}b>zmH}VTkEptBRT3yKXpMms$X@8XAvltr_G2Vapidp4nSY_r3E^O|uhYb6pYC1L zJp1br7x;8yGe95zL?WZ#{zUR1AK64ArP9giZ-tc70fweFOLPKzs1{BK?C3NRh6KTZ}FB$ z(7@5JJOsrdb$<#=SUY$w4oLXe!q~9%p;fVA>BCAhE!p4unKN$zXCXw^NE@QiWX7fn z%w={!_Eg3ua%VC&O<;{=13A+Uo5WfpZBQZ;jvbRT->_lanSn(clZ8OH9YOM)cjg|^ zg(tRjM}A;syYs{q?bH*quMBxSH4&tAwwSPDIb-6dpl(8G5?cHg#%++J=rsv3sVVfZq#2c(Y6z_@b zFy0`!alFBC0(payiR3+$6UrMJHyRtr)lycQfk%odbP3fx2aF}%=ZVp(&7Smw-6?66Prlu!D2Pw-q%@<31O zBv0}PZ#laI|EFDWBItjV0^>|6!SMbMQcwo_WK!%%QuZv;qM2HP!_U7`rNy!-x#rysvN2LaDT)o3+h&ZaKw-wKmsC z{q3`2xg-sF&VNs*>`T)PiqS%cV!q~Ol{Kc918%*+cgs+yqAJD08ZJGT7n!g+1<5cf zGc{76xTjLLc|ZJ3=833!EKa$;)y3GXS6}54M}1X=>6J7u8-o>tUb?(cXH!+TO!rMI z#x3>u*z2;sNFv7&TS;bZuH)r}>4x_Gea^*BEFU;KH-DXIR66+KU zDY{C*fZ*#11U0>yK){e|2@E;ClEBlF>j(rAIC(@6leG%L!j~5c95@T3pwoLlNM>yN z42+5nqzF!IAVFX#!w3NXX)ZQ_+B}q^Xw&DD>3{M`Irsy?i0rBv6jh%%tsxaCNhvuY zl=XcALq+K9)YMGEIWH^IaUkjA2>{}9i49swKy2CqY@V?mXPb99E1_pVb~4vC`&&0P z^Ny|)Z$?B@dUEcGR$ZA_<$sXfegLe`wi3k4Mf0mvQ1E0C=k8S`8P#%&w^+N&&ny{77V2BJ6I1SCm8G; zB6P+@jbYD&#&A3pqpHs&l&;@;#R}k#ghm25ETm+`YXzxy;7^;YwzsDcQ5jOCiow5>=!|-rXF$sr)i@-9PP<1B= zR1xG!p+*vfL!%4(BB>$SL~tA)CnY(89V?-Ka9+Ly%|S8aCQK!<2?)~yZhrxWY@9Sr z!2Vyr?Mc)FZT>-gp+tS$u3N-PO4EmLxj~Jmv^WU+Z85(pF$maZThiLfQU~p{rL3^D z2oReDVdpGO8Z@>dEVi^LXhR&>oXZRfu>ww;dYQ36mcKz4Fh@JR_Vqi4X_}xZxYt@t z(}T?SP!?ob7>LQL`TWX6_h zJY;N)%LK*kbxk8R<8>zFjhRC?iZnV-0NQ$K`Y*DFzdF>!# zdBm|2mkXe}JjWJo35mcO%_ESJGkI;DlyU6nIF+R_P$Xbkr%3KlX@7Co;EohrnCX`B>^Smkko4hSIZv(;lYS4LXSa^E9mrnV4?UeP5WzrynH;}l>|#q09N3vGzB zp!GfgQfX?tN|?SJxc626^DpE4?t`_RaD4mhe!bqmc#wi^e+s@7LIsaT?qyD@#obv`c&-zL_n7k>t+0=v1pl*Id7E2$K*S+Wn(VT(RThyCDt{D`M0^#mW$zaNzm zkIIHeX2JuqU_PgqOGW&nddsOk46*!c=Ri5UuZH6#zL0=}jfu28^x$1X5`mvD!%+br zFGB;9pDx1@Q=k9B(PlH29%jKp;l)1Dfg|ZL>W8ukFj(-&>Uq9|-u`044xwYie{4+UK z#6pPmbDJvA!w*1q-?oX|UTxDjy~HNTr1OEvNn{(wP2oS5=g7%nn<19O4ptzGk3@DF zJ4kLGJ2*}vJ1ChL&=oDBb1-R8%-vcH7AK>&iup<`y@~Kq>uLm&-Ek^^rTMm zB#-d6vpevAhXp5s{u?MT&eRf&;D7rBWw1{s#f~Ip&mt|FX(c%P`YUycNjkp#9~9=r E@yM-GMF0Q* diff --git a/reference/task_manager/index.html b/reference/task_manager/index.html index b58ce0c..2194780 100644 --- a/reference/task_manager/index.html +++ b/reference/task_manager/index.html @@ -557,27 +557,27 @@
  • - + -  register_async_handler +  register_from_dict
  • - + -  unregister_async_handler +  register_async_handler
  • - + -  cli +  unregister_async_handler @@ -956,27 +956,27 @@
  • - + -  register_async_handler +  register_from_dict
  • - + -  unregister_async_handler +  register_async_handler
  • - + -  cli +  unregister_async_handler @@ -1035,7 +1035,13 @@

    Source code in fluid/scheduler/consumer.py -
    55
    +                    
    49
    +50
    +51
    +52
    +53
    +54
    +55
     56
     57
     58
    @@ -1043,27 +1049,21 @@ 

    60 61 62 -63 -64 -65 -66 -67 -68 -69

    def __init__(self, **kwargs: Any) -> None:
    -    self.state: dict[str, Any] = {}
    -    self.config: TaskManagerConfig = TaskManagerConfig(**kwargs)
    -    self.dispatcher: Annotated[
    -        TaskDispatcher,
    -        Doc(
    -            """
    -            A dispatcher of task run events.
    -
    -            Register handlers to listen for task run events.
    -            """
    -        ),
    -    ] = TaskDispatcher()
    -    self.broker = TaskBroker.from_url(self.config.broker_url)
    -    self._stack = AsyncExitStack()
    +63
    def __init__(self, **kwargs: Any) -> None:
    +    self.state: dict[str, Any] = {}
    +    self.config: TaskManagerConfig = TaskManagerConfig(**kwargs)
    +    self.dispatcher: Annotated[
    +        TaskDispatcher,
    +        Doc(
    +            """
    +            A dispatcher of task run events.
    +
    +            Register handlers to listen for task run events.
    +            """
    +        ),
    +    ] = TaskDispatcher()
    +    self.broker = TaskBroker.from_url(self.config.broker_url)
    +    self._stack = AsyncExitStack()
     
    @@ -1224,9 +1224,9 @@

    Source code in fluid/scheduler/consumer.py -
    async def enter_async_context(self, cm: Any) -> Any:
    -    return await self._stack.enter_async_context(cm)
    +              
    async def enter_async_context(self, cm: Any) -> Any:
    +    return await self._stack.enter_async_context(cm)
     
    @@ -1254,15 +1254,15 @@

    Source code in fluid/scheduler/consumer.py -
    91
    -92
    -93
    -94
    -95
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:
    -    """Execute a task and wait for it to finish"""
    -    task_run = self.create_task_run(task, **params)
    -    await task_run.execute()
    -    return task_run
    +              
    85
    +86
    +87
    +88
    +89
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:
    +    """Execute a task and wait for it to finish"""
    +    task_run = self.create_task_run(task, **params)
    +    await task_run.execute()
    +    return task_run
     
    @@ -1288,9 +1288,9 @@

    Source code in fluid/scheduler/consumer.py -
    async def on_shutdown(self) -> None:
    -    await self.broker.close()
    +              
    async def on_shutdown(self) -> None:
    +    await self.broker.close()
     
    @@ -1312,9 +1312,9 @@

    Source code in fluid/scheduler/consumer.py -
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:
    -    return asyncio.run(self._execute_and_exit(task, **params))
    +              
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:
    +    return asyncio.run(self._execute_and_exit(task, **params))
     
    @@ -1339,17 +1339,17 @@

    Source code in fluid/scheduler/consumer.py -
    def register_task(self, task: Task) -> None:
    -    """Register a task with the task manager
    -
    -    Only tasks registered can be executed by a task manager
    -    """
    -    self.broker.register_task(task)
    +              
    def register_task(self, task: Task) -> None:
    +    """Register a task with the task manager
    +
    +    Only tasks registered can be executed by a task manager
    +    """
    +    self.broker.register_task(task)
     
    @@ -1382,7 +1382,13 @@

    Source code in fluid/scheduler/consumer.py -
    110
    +              
    104
    +105
    +106
    +107
    +108
    +109
    +110
     111
     112
     113
    @@ -1393,30 +1399,24 @@ 

    118 119 120 -121 -122 -123 -124 -125 -126 -127

    async def queue(
    -    self,
    -    task: str | Task,
    -    priority: TaskPriority | None = None,
    -    **params: Any,
    -) -> TaskRun:
    -    """Queue a task for execution
    -
    -    This methods fires two events:
    -
    -    - queue: when the task is about to be queued
    -    - queued: after the task is queued
    -    """
    -    task_run = self.create_task_run(task, priority=priority, **params)
    -    self.dispatcher.dispatch(task_run)
    -    task_run.set_state(TaskState.queued)
    -    await self.broker.queue_task(task_run)
    -    return task_run
    +121
    async def queue(
    +    self,
    +    task: str | Task,
    +    priority: TaskPriority | None = None,
    +    **params: Any,
    +) -> TaskRun:
    +    """Queue a task for execution
    +
    +    This methods fires two events:
    +
    +    - queue: when the task is about to be queued
    +    - queued: after the task is queued
    +    """
    +    task_run = self.create_task_run(task, priority=priority, **params)
    +    self.dispatcher.dispatch(task_run)
    +    task_run.set_state(TaskState.queued)
    +    await self.broker.queue_task(task_run)
    +    return task_run
     
    @@ -1440,7 +1440,13 @@

    Source code in fluid/scheduler/consumer.py -
    129
    +              
    123
    +124
    +125
    +126
    +127
    +128
    +129
     130
     131
     132
    @@ -1451,30 +1457,24 @@ 

    137 138 139 -140 -141 -142 -143 -144 -145 -146

    def create_task_run(
    -    self,
    -    task: str | Task,
    -    run_id: str = "",
    -    priority: TaskPriority | None = None,
    -    **params: Any,
    -) -> TaskRun:
    -    """Create a TaskRun in `init` state"""
    -    if isinstance(task, str):
    -        task = self.broker.task_from_registry(task)
    -    run_id = run_id or self.broker.new_uuid()
    -    return TaskRun(
    -        id=run_id,
    -        task=task,
    -        priority=priority or task.priority,
    -        params=params,
    -        task_manager=self,
    -    )
    +140
    def create_task_run(
    +    self,
    +    task: str | Task,
    +    run_id: str = "",
    +    priority: TaskPriority | None = None,
    +    **params: Any,
    +) -> TaskRun:
    +    """Create a TaskRun in `init` state"""
    +    if isinstance(task, str):
    +        task = self.broker.task_from_registry(task)
    +    run_id = run_id or self.broker.new_uuid()
    +    return TaskRun(
    +        id=run_id,
    +        task=task,
    +        priority=priority or task.priority,
    +        params=params,
    +        task_manager=self,
    +    )
     
    @@ -1496,17 +1496,49 @@

    Source code in fluid/scheduler/consumer.py -
    148
    -149
    +              
    def register_from_module(self, module: Any) -> None:
    +    for name in dir(module):
    +        if name.startswith("_"):
    +            continue
    +        if isinstance(obj := getattr(module, name), Task):
    +            self.register_task(obj)
    +
    + +
    + + + +
    + + +

    + register_from_dict + + +

    +
    register_from_dict(data)
    +
    + +
    + +
    + Source code in fluid/scheduler/consumer.py +
    def register_from_module(self, module: Any) -> None:
    -    for name in dir(module):
    -        if name.startswith("_"):
    -            continue
    -        if isinstance(obj := getattr(module, name), Task):
    -            self.register_task(obj)
    +153
    +154
    def register_from_dict(self, data: dict) -> None:
    +    for name, obj in data.items():
    +        if name.startswith("_"):
    +            continue
    +        if isinstance(obj, Task):
    +            self.register_task(obj)
     
    @@ -1531,15 +1563,15 @@

    Source code in fluid/scheduler/consumer.py -
    155
    -156
    +              
    def register_async_handler(self, event: str, handler: AsyncHandler) -> None:
    -    """Register an async handler for a given event
    -
    -    This method is a no op for a TaskManager that is not a worker
    -    """
    +159
    +160
    def register_async_handler(self, event: str, handler: AsyncHandler) -> None:
    +    """Register an async handler for a given event
    +
    +    This method is a no op for a TaskManager that is not a worker
    +    """
     
    @@ -1564,59 +1596,17 @@

    Source code in fluid/scheduler/consumer.py -
    161
    -162
    +              
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:
    -    """Unregister an async handler for a given event
    -
    -    This method is a no op for a TaskManager that is not a worker
    -    """
    -    return None
    -
    - -
    - - - -
    - - -

    - cli - - -

    -
    cli(**kwargs)
    -
    - -
    - -

    Create the task manager command line interface

    - -
    - Source code in fluid/scheduler/consumer.py -
    def cli(self, **kwargs: Any) -> Any:
    -    """Create the task manager command line interface"""
    -    try:
    -        from fluid.scheduler.cli import TaskManagerCLI
    -    except ImportError:
    -        raise ImportError(
    -            "TaskManagerCLI is not available - "
    -            "install with `pip install aio-fluid[cli]`"
    -        ) from None
    -    return TaskManagerCLI(self, **kwargs)
    +166
    +167
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:
    +    """Unregister an async handler for a given event
    +
    +    This method is a no op for a TaskManager that is not a worker
    +    """
    +    return None
     
    diff --git a/reference/tast_consumer/index.html b/reference/tast_consumer/index.html index 6896682..2ed5196 100644 --- a/reference/tast_consumer/index.html +++ b/reference/tast_consumer/index.html @@ -770,9 +770,9 @@
  • - + -  cli +  register_from_dict @@ -1334,9 +1334,9 @@
  • - + -  cli +  register_from_dict @@ -1452,7 +1452,17 @@

    Source code in fluid/scheduler/consumer.py -
    189
    +                    
    179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
     190
     191
     192
    @@ -1460,35 +1470,25 @@ 

    194 195 196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207

    def __init__(self, **config: Any) -> None:
    -    super().__init__(**config)
    -    Workers.__init__(self)
    -    self._async_dispatcher_worker = AsyncConsumer(AsyncTaskDispatcher())
    -    self._concurrent_tasks: dict[str, dict[str, TaskRun]] = defaultdict(dict)
    -    self._task_to_queue: deque[str | Task] = deque()
    -    self._priority_task_run_queue: deque[TaskRun] = deque()
    -    self._queue_tasks_worker = WorkerFunction(
    -        self._queue_task, name="queue-task-worker"
    -    )
    -    self.add_workers(self._queue_tasks_worker)
    -    self.add_workers(self._async_dispatcher_worker)
    -    for i in range(self.config.max_concurrent_tasks):
    -        worker_name = f"task-worker-{i+1}"
    -        self.add_workers(
    -            WorkerFunction(
    -                partial(self._consume_tasks, worker_name), name=worker_name
    -            )
    -        )
    +197
    def __init__(self, **config: Any) -> None:
    +    super().__init__(**config)
    +    Workers.__init__(self)
    +    self._async_dispatcher_worker = AsyncConsumer(AsyncTaskDispatcher())
    +    self._concurrent_tasks: dict[str, dict[str, TaskRun]] = defaultdict(dict)
    +    self._task_to_queue: deque[str | Task] = deque()
    +    self._priority_task_run_queue: deque[TaskRun] = deque()
    +    self._queue_tasks_worker = WorkerFunction(
    +        self._queue_task, name="queue-task-worker"
    +    )
    +    self.add_workers(self._queue_tasks_worker)
    +    self.add_workers(self._async_dispatcher_worker)
    +    for i in range(self.config.max_concurrent_tasks):
    +        worker_name = f"task-worker-{i+1}"
    +        self.add_workers(
    +            WorkerFunction(
    +                partial(self._consume_tasks, worker_name), name=worker_name
    +            )
    +        )
     
    @@ -2019,9 +2019,9 @@

    Source code in fluid/scheduler/consumer.py -
    async def on_shutdown(self) -> None:
    -    await self.broker.close()
    +              
    async def on_shutdown(self) -> None:
    +    await self.broker.close()
     
    @@ -2372,9 +2372,9 @@

    Source code in fluid/scheduler/consumer.py -
    async def enter_async_context(self, cm: Any) -> Any:
    -    return await self._stack.enter_async_context(cm)
    +              
    async def enter_async_context(self, cm: Any) -> Any:
    +    return await self._stack.enter_async_context(cm)
     
    @@ -2402,15 +2402,15 @@

    Source code in fluid/scheduler/consumer.py -
    91
    -92
    -93
    -94
    -95
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:
    -    """Execute a task and wait for it to finish"""
    -    task_run = self.create_task_run(task, **params)
    -    await task_run.execute()
    -    return task_run
    +              
    85
    +86
    +87
    +88
    +89
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:
    +    """Execute a task and wait for it to finish"""
    +    task_run = self.create_task_run(task, **params)
    +    await task_run.execute()
    +    return task_run
     
    @@ -2432,9 +2432,9 @@

    Source code in fluid/scheduler/consumer.py -
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:
    -    return asyncio.run(self._execute_and_exit(task, **params))
    +              
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:
    +    return asyncio.run(self._execute_and_exit(task, **params))
     
    @@ -2459,17 +2459,17 @@

    Source code in fluid/scheduler/consumer.py -
    def register_task(self, task: Task) -> None:
    -    """Register a task with the task manager
    -
    -    Only tasks registered can be executed by a task manager
    -    """
    -    self.broker.register_task(task)
    +              
    def register_task(self, task: Task) -> None:
    +    """Register a task with the task manager
    +
    +    Only tasks registered can be executed by a task manager
    +    """
    +    self.broker.register_task(task)
     
    @@ -2502,7 +2502,13 @@

    Source code in fluid/scheduler/consumer.py -
    110
    +              
    104
    +105
    +106
    +107
    +108
    +109
    +110
     111
     112
     113
    @@ -2513,30 +2519,24 @@ 

    118 119 120 -121 -122 -123 -124 -125 -126 -127

    async def queue(
    -    self,
    -    task: str | Task,
    -    priority: TaskPriority | None = None,
    -    **params: Any,
    -) -> TaskRun:
    -    """Queue a task for execution
    -
    -    This methods fires two events:
    -
    -    - queue: when the task is about to be queued
    -    - queued: after the task is queued
    -    """
    -    task_run = self.create_task_run(task, priority=priority, **params)
    -    self.dispatcher.dispatch(task_run)
    -    task_run.set_state(TaskState.queued)
    -    await self.broker.queue_task(task_run)
    -    return task_run
    +121
    async def queue(
    +    self,
    +    task: str | Task,
    +    priority: TaskPriority | None = None,
    +    **params: Any,
    +) -> TaskRun:
    +    """Queue a task for execution
    +
    +    This methods fires two events:
    +
    +    - queue: when the task is about to be queued
    +    - queued: after the task is queued
    +    """
    +    task_run = self.create_task_run(task, priority=priority, **params)
    +    self.dispatcher.dispatch(task_run)
    +    task_run.set_state(TaskState.queued)
    +    await self.broker.queue_task(task_run)
    +    return task_run
     
    @@ -2560,7 +2560,13 @@

    Source code in fluid/scheduler/consumer.py -
    129
    +              
    123
    +124
    +125
    +126
    +127
    +128
    +129
     130
     131
     132
    @@ -2571,30 +2577,24 @@ 

    137 138 139 -140 -141 -142 -143 -144 -145 -146

    def create_task_run(
    -    self,
    -    task: str | Task,
    -    run_id: str = "",
    -    priority: TaskPriority | None = None,
    -    **params: Any,
    -) -> TaskRun:
    -    """Create a TaskRun in `init` state"""
    -    if isinstance(task, str):
    -        task = self.broker.task_from_registry(task)
    -    run_id = run_id or self.broker.new_uuid()
    -    return TaskRun(
    -        id=run_id,
    -        task=task,
    -        priority=priority or task.priority,
    -        params=params,
    -        task_manager=self,
    -    )
    +140
    def create_task_run(
    +    self,
    +    task: str | Task,
    +    run_id: str = "",
    +    priority: TaskPriority | None = None,
    +    **params: Any,
    +) -> TaskRun:
    +    """Create a TaskRun in `init` state"""
    +    if isinstance(task, str):
    +        task = self.broker.task_from_registry(task)
    +    run_id = run_id or self.broker.new_uuid()
    +    return TaskRun(
    +        id=run_id,
    +        task=task,
    +        priority=priority or task.priority,
    +        params=params,
    +        task_manager=self,
    +    )
     
    @@ -2616,17 +2616,17 @@

    Source code in fluid/scheduler/consumer.py -
    def register_from_module(self, module: Any) -> None:
    -    for name in dir(module):
    -        if name.startswith("_"):
    -            continue
    -        if isinstance(obj := getattr(module, name), Task):
    -            self.register_task(obj)
    +              
    def register_from_module(self, module: Any) -> None:
    +    for name in dir(module):
    +        if name.startswith("_"):
    +            continue
    +        if isinstance(obj := getattr(module, name), Task):
    +            self.register_task(obj)
     
    @@ -2636,39 +2636,29 @@

    -

    - cli +

    + register_from_dict -

    -
    cli(**kwargs)
    +
    +
    register_from_dict(data)
     
    -

    Create the task manager command line interface

    -
    Source code in fluid/scheduler/consumer.py -
    def cli(self, **kwargs: Any) -> Any:
    -    """Create the task manager command line interface"""
    -    try:
    -        from fluid.scheduler.cli import TaskManagerCLI
    -    except ImportError:
    -        raise ImportError(
    -            "TaskManagerCLI is not available - "
    -            "install with `pip install aio-fluid[cli]`"
    -        ) from None
    -    return TaskManagerCLI(self, **kwargs)
    +              
    def register_from_dict(self, data: dict) -> None:
    +    for name, obj in data.items():
    +        if name.startswith("_"):
    +            continue
    +        if isinstance(obj, Task):
    +            self.register_task(obj)
     
    @@ -2690,9 +2680,9 @@

    Source code in fluid/scheduler/consumer.py -
    def sync_queue(self, task: str | Task) -> None:
    -    self._task_to_queue.appendleft(task)
    +              
    def sync_queue(self, task: str | Task) -> None:
    +    self._task_to_queue.appendleft(task)
     
    @@ -2714,9 +2704,9 @@

    Source code in fluid/scheduler/consumer.py -
    def sync_priority_queue(self, task: str | Task) -> None:
    -    self._priority_task_run_queue.appendleft(self.create_task_run(task))
    +              
    def sync_priority_queue(self, task: str | Task) -> None:
    +    self._priority_task_run_queue.appendleft(self.create_task_run(task))
     
    @@ -2740,11 +2730,11 @@

    Source code in fluid/scheduler/consumer.py -
    def num_concurrent_tasks_for(self, task_name: str) -> int:
    -    """The number of concurrent tasks for a given task_name"""
    -    return len(self._concurrent_tasks[task_name])
    +              
    def num_concurrent_tasks_for(self, task_name: str) -> int:
    +    """The number of concurrent tasks for a given task_name"""
    +    return len(self._concurrent_tasks[task_name])
     
    @@ -2772,17 +2762,17 @@

    Source code in fluid/scheduler/consumer.py -
    async def queue_and_wait(
    -    self, task: str, *, timeout: int = 2, **params: Any
    -) -> TaskRun:
    -    """Queue a task and wait for it to finish"""
    -    with TaskRunWaiter(self) as waiter:
    -        return await waiter.wait(await self.queue(task, **params), timeout=timeout)
    +              
    async def queue_and_wait(
    +    self, task: str, *, timeout: int = 2, **params: Any
    +) -> TaskRun:
    +    """Queue a task and wait for it to finish"""
    +    with TaskRunWaiter(self) as waiter:
    +        return await waiter.wait(await self.queue(task, **params), timeout=timeout)
     
    @@ -2804,19 +2794,19 @@

    Source code in fluid/scheduler/consumer.py -
    def register_async_handler(self, event: Event | str, handler: AsyncHandler) -> None:
    -    event = Event.from_string_or_event(event)
    -    self.dispatcher.register_handler(
    -        f"{event.type}.async_dispatch",
    -        self._async_dispatcher_worker.send,
    -    )
    -    self._async_dispatcher_worker.dispatcher.register_handler(event, handler)
    +              
    def register_async_handler(self, event: Event | str, handler: AsyncHandler) -> None:
    +    event = Event.from_string_or_event(event)
    +    self.dispatcher.register_handler(
    +        f"{event.type}.async_dispatch",
    +        self._async_dispatcher_worker.send,
    +    )
    +    self._async_dispatcher_worker.dispatcher.register_handler(event, handler)
     
    @@ -2838,9 +2828,9 @@

    Source code in fluid/scheduler/consumer.py -
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:
    -    return self._async_dispatcher_worker.dispatcher.unregister_handler(event)
    +              
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:
    +    return self._async_dispatcher_worker.dispatcher.unregister_handler(event)
     
    diff --git a/search/search_index.json b/search/search_index.json index 5de5d46..635e063 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"

    Aio Fluid

    Async utilities for backend python services developed by Quantmind.

    Documentation: https://quantmind.github.io/aio-fluid

    Source Code: https://github.com/quantmind/aio-fluid

    "},{"location":"#installation","title":"Installation","text":"

    This is a simple python package you can install via pip:

    pip install aio-fluid\n

    To install all the dependencies:

    pip install aio-fluid[cli, db, http, log]\n
    this includes the following extra dependencies:

    • cli for the command line interface using click and rich
    • db for database support with asyncpg and sqlalchemy
    • http for http client support with httpx and aiohttp
    • log for JSON logging support with python-json-logger
    "},{"location":"#development","title":"Development","text":"

    You can run the examples via

    poetry run python -m examples.main\n
    "},{"location":"reference/","title":"Introduction","text":"

    Here's the reference or code API, the classes, functions, parameters, attributes, and all the aio-fluid parts you can use in your applications.

    "},{"location":"reference/dispatchers/","title":"Event Dispatchers","text":"

    A set of classes for dispatching events, they can be imported from fluid.utils.dispatcher:

    from fluid.utils.dispatcher import Dispatcher\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher","title":"fluid.utils.dispatcher.BaseDispatcher","text":"
    BaseDispatcher()\n

    Bases: Generic[MessageType, MessageHandlerType], ABC

    Source code in fluid/utils/dispatcher.py
    def __init__(self) -> None:\n    self._msg_handlers: defaultdict[str, dict[str, MessageHandlerType]] = (\n        defaultdict(\n            dict,\n        )\n    )\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.register_handler","title":"register_handler","text":"
    register_handler(event, handler)\n
    Source code in fluid/utils/dispatcher.py
    def register_handler(\n    self,\n    event: Event | str,\n    handler: MessageHandlerType,\n) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    previous = self._msg_handlers[event.type].get(event.tag)\n    self._msg_handlers[event.type][event.tag] = handler\n    return previous\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.unregister_handler","title":"unregister_handler","text":"
    unregister_handler(event)\n
    Source code in fluid/utils/dispatcher.py
    def unregister_handler(self, event: Event | str) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    return self._msg_handlers[event.type].pop(event.tag, None)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.get_handlers","title":"get_handlers","text":"
    get_handlers(message)\n
    Source code in fluid/utils/dispatcher.py
    def get_handlers(\n    self,\n    message: MessageType,\n) -> dict[str, MessageHandlerType] | None:\n    message_type = str(self.message_type(message))\n    return self._msg_handlers.get(message_type)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.message_type","title":"message_type abstractmethod","text":"
    message_type(message)\n

    return the message type

    Source code in fluid/utils/dispatcher.py
    @abstractmethod\ndef message_type(self, message: MessageType) -> str:\n    \"\"\"return the message type\"\"\"\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher","title":"fluid.utils.dispatcher.Dispatcher","text":"
    Dispatcher()\n

    Bases: BaseDispatcher[MessageType, Callable[[MessageType], None]]

    Dispatcher for sync handlers

    Source code in fluid/utils/dispatcher.py
    def __init__(self) -> None:\n    self._msg_handlers: defaultdict[str, dict[str, MessageHandlerType]] = (\n        defaultdict(\n            dict,\n        )\n    )\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.register_handler","title":"register_handler","text":"
    register_handler(event, handler)\n
    Source code in fluid/utils/dispatcher.py
    def register_handler(\n    self,\n    event: Event | str,\n    handler: MessageHandlerType,\n) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    previous = self._msg_handlers[event.type].get(event.tag)\n    self._msg_handlers[event.type][event.tag] = handler\n    return previous\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.unregister_handler","title":"unregister_handler","text":"
    unregister_handler(event)\n
    Source code in fluid/utils/dispatcher.py
    def unregister_handler(self, event: Event | str) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    return self._msg_handlers[event.type].pop(event.tag, None)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.get_handlers","title":"get_handlers","text":"
    get_handlers(message)\n
    Source code in fluid/utils/dispatcher.py
    def get_handlers(\n    self,\n    message: MessageType,\n) -> dict[str, MessageHandlerType] | None:\n    message_type = str(self.message_type(message))\n    return self._msg_handlers.get(message_type)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.message_type","title":"message_type abstractmethod","text":"
    message_type(message)\n

    return the message type

    Source code in fluid/utils/dispatcher.py
    @abstractmethod\ndef message_type(self, message: MessageType) -> str:\n    \"\"\"return the message type\"\"\"\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.dispatch","title":"dispatch","text":"
    dispatch(message)\n

    dispatch the message

    Source code in fluid/utils/dispatcher.py
    def dispatch(self, message: MessageType) -> int:\n    \"\"\"dispatch the message\"\"\"\n    handlers = self.get_handlers(message)\n    if handlers:\n        for handler in handlers.values():\n            handler(message)\n    return len(handlers or ())\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher","title":"fluid.utils.dispatcher.AsyncDispatcher","text":"
    AsyncDispatcher()\n

    Bases: BaseDispatcher[MessageType, Callable[[MessageType], Awaitable[None]]]

    Dispatcher for async handlers

    Source code in fluid/utils/dispatcher.py
    def __init__(self) -> None:\n    self._msg_handlers: defaultdict[str, dict[str, MessageHandlerType]] = (\n        defaultdict(\n            dict,\n        )\n    )\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.register_handler","title":"register_handler","text":"
    register_handler(event, handler)\n
    Source code in fluid/utils/dispatcher.py
    def register_handler(\n    self,\n    event: Event | str,\n    handler: MessageHandlerType,\n) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    previous = self._msg_handlers[event.type].get(event.tag)\n    self._msg_handlers[event.type][event.tag] = handler\n    return previous\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.unregister_handler","title":"unregister_handler","text":"
    unregister_handler(event)\n
    Source code in fluid/utils/dispatcher.py
    def unregister_handler(self, event: Event | str) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    return self._msg_handlers[event.type].pop(event.tag, None)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.get_handlers","title":"get_handlers","text":"
    get_handlers(message)\n
    Source code in fluid/utils/dispatcher.py
    def get_handlers(\n    self,\n    message: MessageType,\n) -> dict[str, MessageHandlerType] | None:\n    message_type = str(self.message_type(message))\n    return self._msg_handlers.get(message_type)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.message_type","title":"message_type abstractmethod","text":"
    message_type(message)\n

    return the message type

    Source code in fluid/utils/dispatcher.py
    @abstractmethod\ndef message_type(self, message: MessageType) -> str:\n    \"\"\"return the message type\"\"\"\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.dispatch","title":"dispatch async","text":"
    dispatch(message)\n

    Dispatch the message and wait for all handlers to complete

    Source code in fluid/utils/dispatcher.py
    async def dispatch(self, message: MessageType) -> int:\n    \"\"\"Dispatch the message and wait for all handlers to complete\"\"\"\n    handlers = self.get_handlers(message)\n    if handlers:\n        await asyncio.gather(*[handler(message) for handler in handlers.values()])\n    return len(handlers or ())\n
    "},{"location":"reference/task_broker/","title":"Task Broker","text":"

    It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskBroker\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker","title":"fluid.scheduler.TaskBroker","text":"
    TaskBroker(url)\n

    Bases: ABC

    Source code in fluid/scheduler/broker.py
    def __init__(self, url: URL) -> None:\n    self.url: URL = url\n    self.registry: TaskRegistry = TaskRegistry()\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.url","title":"url instance-attribute","text":"
    url = url\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.registry","title":"registry instance-attribute","text":"
    registry = TaskRegistry()\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.task_queue_names","title":"task_queue_names abstractmethod property","text":"
    task_queue_names\n

    Names of the task queues

    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.queue_task","title":"queue_task abstractmethod async","text":"
    queue_task(task_run)\n

    Queue a task

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def queue_task(self, task_run: TaskRun) -> None:\n    \"\"\"Queue a task\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.get_task_run","title":"get_task_run abstractmethod async","text":"
    get_task_run(task_manager)\n

    Get a Task run from the task queue

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def get_task_run(self, task_manager: TaskManager) -> TaskRun | None:\n    \"\"\"Get a Task run from the task queue\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.queue_length","title":"queue_length abstractmethod async","text":"
    queue_length()\n

    Length of task queues

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def queue_length(self) -> dict[str, int]:\n    \"\"\"Length of task queues\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.get_tasks_info","title":"get_tasks_info abstractmethod async","text":"
    get_tasks_info(*task_names)\n

    List of TaskInfo objects

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def get_tasks_info(self, *task_names: str) -> list[TaskInfo]:\n    \"\"\"List of TaskInfo objects\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.update_task","title":"update_task abstractmethod async","text":"
    update_task(task, params)\n

    Update a task dynamic parameters

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def update_task(self, task: Task, params: dict[str, Any]) -> TaskInfo:\n    \"\"\"Update a task dynamic parameters\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.close","title":"close abstractmethod async","text":"
    close()\n

    Close the broker on shutdown

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def close(self) -> None:\n    \"\"\"Close the broker on shutdown\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.lock","title":"lock abstractmethod","text":"
    lock(name, timeout=None)\n

    Create a lock

    Source code in fluid/scheduler/broker.py
    @abstractmethod\ndef lock(self, name: str, timeout: float | None = None) -> Lock:\n    \"\"\"Create a lock\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.new_uuid","title":"new_uuid","text":"
    new_uuid()\n
    Source code in fluid/scheduler/broker.py
    def new_uuid(self) -> str:\n    return uuid4().hex\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.filter_tasks","title":"filter_tasks async","text":"
    filter_tasks(scheduled=None, enabled=None)\n
    Source code in fluid/scheduler/broker.py
    async def filter_tasks(\n    self,\n    scheduled: bool | None = None,\n    enabled: bool | None = None,\n) -> list[Task]:\n    task_info = await self.get_tasks_info()\n    task_map = {info.name: info for info in task_info}\n    tasks = []\n    for task in self.registry.values():\n        if scheduled is not None and bool(task.schedule) is not scheduled:\n            continue\n        if enabled is not None and task_map[task.name].enabled is not enabled:\n            continue\n        tasks.append(task)\n    return tasks\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.task_from_registry","title":"task_from_registry","text":"
    task_from_registry(task)\n
    Source code in fluid/scheduler/broker.py
    def task_from_registry(self, task: str | Task) -> Task:\n    if isinstance(task, Task):\n        self.register_task(task)\n        return task\n    else:\n        if task_ := self.registry.get(task):\n            return task_\n        raise UnknownTaskError(task)\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.register_task","title":"register_task","text":"
    register_task(task)\n
    Source code in fluid/scheduler/broker.py
    def register_task(self, task: Task) -> None:\n    self.registry[task.name] = task\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.enable_task","title":"enable_task async","text":"
    enable_task(task_name, enable=True)\n

    Enable or disable a registered task

    Source code in fluid/scheduler/broker.py
    async def enable_task(self, task_name: str, enable: bool = True) -> TaskInfo:\n    \"\"\"Enable or disable a registered task\"\"\"\n    task = self.registry.get(task_name)\n    if not task:\n        raise UnknownTaskError(task_name)\n    return await self.update_task(task, dict(enabled=enable))\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.from_url","title":"from_url classmethod","text":"
    from_url(url='')\n
    Source code in fluid/scheduler/broker.py
    @classmethod\ndef from_url(cls, url: str = \"\") -> TaskBroker:\n    p = URL(url or broker_url_from_env())\n    if factory := _brokers.get(p.scheme):\n        return factory(p)\n    raise RuntimeError(f\"Invalid broker {p}\")\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.register_broker","title":"register_broker classmethod","text":"
    register_broker(name, factory)\n
    Source code in fluid/scheduler/broker.py
    @classmethod\ndef register_broker(cls, name: str, factory: type[TaskBroker]) -> None:\n    _brokers[name] = factory\n
    "},{"location":"reference/task_manager/","title":"Task Manager","text":"

    It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskManager\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager","title":"fluid.scheduler.TaskManager","text":"
    TaskManager(**kwargs)\n

    The task manager is the main entry point for managing tasks

    Source code in fluid/scheduler/consumer.py
    def __init__(self, **kwargs: Any) -> None:\n    self.state: dict[str, Any] = {}\n    self.config: TaskManagerConfig = TaskManagerConfig(**kwargs)\n    self.dispatcher: Annotated[\n        TaskDispatcher,\n        Doc(\n            \"\"\"\n            A dispatcher of task run events.\n\n            Register handlers to listen for task run events.\n            \"\"\"\n        ),\n    ] = TaskDispatcher()\n    self.broker = TaskBroker.from_url(self.config.broker_url)\n    self._stack = AsyncExitStack()\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.state","title":"state instance-attribute","text":"
    state = {}\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.config","title":"config instance-attribute","text":"
    config = TaskManagerConfig(**kwargs)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.dispatcher","title":"dispatcher instance-attribute","text":"
    dispatcher = TaskDispatcher()\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.broker","title":"broker instance-attribute","text":"
    broker = from_url(broker_url)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.registry","title":"registry property","text":"
    registry\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.type","title":"type property","text":"
    type\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.enter_async_context","title":"enter_async_context async","text":"
    enter_async_context(cm)\n
    Source code in fluid/scheduler/consumer.py
    async def enter_async_context(self, cm: Any) -> Any:\n    return await self._stack.enter_async_context(cm)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.execute","title":"execute async","text":"
    execute(task, **params)\n

    Execute a task and wait for it to finish

    Source code in fluid/scheduler/consumer.py
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:\n    \"\"\"Execute a task and wait for it to finish\"\"\"\n    task_run = self.create_task_run(task, **params)\n    await task_run.execute()\n    return task_run\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n
    Source code in fluid/scheduler/consumer.py
    async def on_shutdown(self) -> None:\n    await self.broker.close()\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.execute_sync","title":"execute_sync","text":"
    execute_sync(task, **params)\n
    Source code in fluid/scheduler/consumer.py
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:\n    return asyncio.run(self._execute_and_exit(task, **params))\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.register_task","title":"register_task","text":"
    register_task(task)\n

    Register a task with the task manager

    Only tasks registered can be executed by a task manager

    Source code in fluid/scheduler/consumer.py
    def register_task(self, task: Task) -> None:\n    \"\"\"Register a task with the task manager\n\n    Only tasks registered can be executed by a task manager\n    \"\"\"\n    self.broker.register_task(task)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.queue","title":"queue async","text":"
    queue(task, priority=None, **params)\n

    Queue a task for execution

    This methods fires two events:

    • queue: when the task is about to be queued
    • queued: after the task is queued
    Source code in fluid/scheduler/consumer.py
    async def queue(\n    self,\n    task: str | Task,\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Queue a task for execution\n\n    This methods fires two events:\n\n    - queue: when the task is about to be queued\n    - queued: after the task is queued\n    \"\"\"\n    task_run = self.create_task_run(task, priority=priority, **params)\n    self.dispatcher.dispatch(task_run)\n    task_run.set_state(TaskState.queued)\n    await self.broker.queue_task(task_run)\n    return task_run\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.create_task_run","title":"create_task_run","text":"
    create_task_run(task, run_id='', priority=None, **params)\n

    Create a TaskRun in init state

    Source code in fluid/scheduler/consumer.py
    def create_task_run(\n    self,\n    task: str | Task,\n    run_id: str = \"\",\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Create a TaskRun in `init` state\"\"\"\n    if isinstance(task, str):\n        task = self.broker.task_from_registry(task)\n    run_id = run_id or self.broker.new_uuid()\n    return TaskRun(\n        id=run_id,\n        task=task,\n        priority=priority or task.priority,\n        params=params,\n        task_manager=self,\n    )\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.register_from_module","title":"register_from_module","text":"
    register_from_module(module)\n
    Source code in fluid/scheduler/consumer.py
    def register_from_module(self, module: Any) -> None:\n    for name in dir(module):\n        if name.startswith(\"_\"):\n            continue\n        if isinstance(obj := getattr(module, name), Task):\n            self.register_task(obj)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.register_async_handler","title":"register_async_handler","text":"
    register_async_handler(event, handler)\n

    Register an async handler for a given event

    This method is a no op for a TaskManager that is not a worker

    Source code in fluid/scheduler/consumer.py
    def register_async_handler(self, event: str, handler: AsyncHandler) -> None:\n    \"\"\"Register an async handler for a given event\n\n    This method is a no op for a TaskManager that is not a worker\n    \"\"\"\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.unregister_async_handler","title":"unregister_async_handler","text":"
    unregister_async_handler(event)\n

    Unregister an async handler for a given event

    This method is a no op for a TaskManager that is not a worker

    Source code in fluid/scheduler/consumer.py
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:\n    \"\"\"Unregister an async handler for a given event\n\n    This method is a no op for a TaskManager that is not a worker\n    \"\"\"\n    return None\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.cli","title":"cli","text":"
    cli(**kwargs)\n

    Create the task manager command line interface

    Source code in fluid/scheduler/consumer.py
    def cli(self, **kwargs: Any) -> Any:\n    \"\"\"Create the task manager command line interface\"\"\"\n    try:\n        from fluid.scheduler.cli import TaskManagerCLI\n    except ImportError:\n        raise ImportError(\n            \"TaskManagerCLI is not available - \"\n            \"install with `pip install aio-fluid[cli]`\"\n        ) from None\n    return TaskManagerCLI(self, **kwargs)\n
    "},{"location":"reference/task_run/","title":"Task Run","text":"

    It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskRun\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun","title":"fluid.scheduler.TaskRun","text":"

    Bases: BaseModel

    A TaskRun contains all the data generated by a Task run

    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.id","title":"id instance-attribute","text":"
    id\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.task","title":"task instance-attribute","text":"
    task\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.priority","title":"priority instance-attribute","text":"
    priority\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.params","title":"params instance-attribute","text":"
    params\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.state","title":"state class-attribute instance-attribute","text":"
    state = init\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.task_manager","title":"task_manager class-attribute instance-attribute","text":"
    task_manager = Field(exclude=True, repr=False)\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.queued","title":"queued class-attribute instance-attribute","text":"
    queued = None\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.start","title":"start class-attribute instance-attribute","text":"
    start = None\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.end","title":"end class-attribute instance-attribute","text":"
    end = None\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.logger","title":"logger property","text":"
    logger\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.in_queue","title":"in_queue property","text":"
    in_queue\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.duration","title":"duration property","text":"
    duration\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.duration_ms","title":"duration_ms property","text":"
    duration_ms\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.total","title":"total property","text":"
    total\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.name","title":"name property","text":"
    name\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.name_id","title":"name_id property","text":"
    name_id\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.is_done","title":"is_done property","text":"
    is_done\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.is_failure","title":"is_failure property","text":"
    is_failure\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.execute","title":"execute async","text":"
    execute()\n
    Source code in fluid/scheduler/models.py
    async def execute(self) -> None:\n    try:\n        self.set_state(TaskState.running)\n        await self.task.executor(self)\n    except Exception:\n        self.set_state(TaskState.failure)\n        raise\n    else:\n        self.set_state(TaskState.success)\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.serialize_task","title":"serialize_task","text":"
    serialize_task(task, _info)\n
    Source code in fluid/scheduler/models.py
    @field_serializer(\"task\")\ndef serialize_task(self, task: Task, _info: Any) -> str:\n    return task.name\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.params_dump_json","title":"params_dump_json","text":"
    params_dump_json()\n
    Source code in fluid/scheduler/models.py
    def params_dump_json(self) -> str:\n    return self.task.params_dump_json(self.params)\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.set_state","title":"set_state","text":"
    set_state(state, state_time=None)\n
    Source code in fluid/scheduler/models.py
    def set_state(\n    self,\n    state: TaskState,\n    state_time: datetime | None = None,\n) -> None:\n    if self.state == state:\n        return\n    state_time = as_utc(state_time)\n    match (self.state, state):\n        case (TaskState.init, TaskState.queued):\n            self.queued = state_time\n            self.state = state\n            self._dispatch()\n        case (TaskState.init, _):\n            self.set_state(TaskState.queued, state_time)\n            self.set_state(state, state_time)\n        case (TaskState.queued, TaskState.running):\n            self.start = state_time\n            self.state = state\n            self._dispatch()\n        case (\n            TaskState.queued,\n            TaskState.success\n            | TaskState.aborted\n            | TaskState.rate_limited\n            | TaskState.failure,\n        ):\n            self.set_state(TaskState.running, state_time)\n            self.set_state(state, state_time)\n        case (\n            TaskState.running,\n            TaskState.success\n            | TaskState.aborted\n            | TaskState.rate_limited\n            | TaskState.failure,\n        ):\n            self.end = state_time\n            self.state = state\n            self._dispatch()\n        case _:\n            raise TaskRunError(f\"invalid state transition {self.state} -> {state}\")\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.lock","title":"lock","text":"
    lock(timeout)\n
    Source code in fluid/scheduler/models.py
    def lock(self, timeout: float | None) -> Lock:\n    return self.task_manager.broker.lock(self.name, timeout=timeout)\n
    "},{"location":"reference/tast_consumer/","title":"Task Consumer","text":"

    The task consumer is a TaskManager which is also a Workers that consumes tasks from the task queue and executes them. It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskConsumer\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer","title":"fluid.scheduler.TaskConsumer","text":"
    TaskConsumer(**config)\n

    Bases: TaskManager, Workers

    The Task Consumer is a Task Manager responsible for consuming tasks from a task queue

    Source code in fluid/scheduler/consumer.py
    def __init__(self, **config: Any) -> None:\n    super().__init__(**config)\n    Workers.__init__(self)\n    self._async_dispatcher_worker = AsyncConsumer(AsyncTaskDispatcher())\n    self._concurrent_tasks: dict[str, dict[str, TaskRun]] = defaultdict(dict)\n    self._task_to_queue: deque[str | Task] = deque()\n    self._priority_task_run_queue: deque[TaskRun] = deque()\n    self._queue_tasks_worker = WorkerFunction(\n        self._queue_task, name=\"queue-task-worker\"\n    )\n    self.add_workers(self._queue_tasks_worker)\n    self.add_workers(self._async_dispatcher_worker)\n    for i in range(self.config.max_concurrent_tasks):\n        worker_name = f\"task-worker-{i+1}\"\n        self.add_workers(\n            WorkerFunction(\n                partial(self._consume_tasks, worker_name), name=worker_name\n            )\n        )\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.num_workers","title":"num_workers property","text":"
    num_workers\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.running","title":"running property","text":"
    running\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.state","title":"state instance-attribute","text":"
    state = {}\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.config","title":"config instance-attribute","text":"
    config = TaskManagerConfig(**kwargs)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.dispatcher","title":"dispatcher instance-attribute","text":"
    dispatcher = TaskDispatcher()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.broker","title":"broker instance-attribute","text":"
    broker = from_url(broker_url)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.registry","title":"registry property","text":"
    registry\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.type","title":"type property","text":"
    type\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.num_concurrent_tasks","title":"num_concurrent_tasks property","text":"
    num_concurrent_tasks\n

    The number of concurrent_tasks running in the consumer

    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return await self._workers.status()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._workers.gracefully_stop()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._workers.is_stopping()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.run","title":"run async","text":"
    run()\n

    run the workers

    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    \"\"\"run the workers\"\"\"\n    with self.start_running():\n        async with self.safe_run():\n            workers, _ = self._workers.workers_tasks()\n            self._workers.workers = tuple(workers)\n            self._workers.tasks = tuple(\n                self.create_task(worker) for worker in workers\n            )\n            await asyncio.gather(*self._workers.tasks)\n        await self.shutdown()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.add_workers","title":"add_workers","text":"
    add_workers(*workers)\n

    add workers to the workers

    Source code in fluid/utils/worker.py
    def add_workers(self, *workers: Worker) -> None:\n    \"\"\"add workers to the workers\"\"\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        if worker not in workers_:\n            workers_.append(worker)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.wait_for_exit","title":"wait_for_exit async","text":"
    wait_for_exit()\n
    Source code in fluid/utils/worker.py
    async def wait_for_exit(self) -> None:\n    if self._workers_task is not None:\n        await self._workers_task\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.create_task","title":"create_task","text":"
    create_task(worker)\n
    Source code in fluid/utils/worker.py
    def create_task(self, worker: Worker) -> asyncio.Task:\n    return asyncio.create_task(\n        self._run_worker(worker), name=f\"{self.worker_name}-{worker.worker_name}\"\n    )\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n
    Source code in fluid/scheduler/consumer.py
    async def on_shutdown(self) -> None:\n    await self.broker.close()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.shutdown","title":"shutdown async","text":"
    shutdown()\n

    shutdown the workers

    Source code in fluid/utils/worker.py
    async def shutdown(self) -> None:\n    \"\"\"shutdown the workers\"\"\"\n    if self._has_shutdown:\n        return\n    self._has_shutdown = True\n    logger.warning(\n        \"gracefully stopping %d workers: %s\",\n        self.num_workers,\n        \", \".join(w.worker_name for w in self._workers.workers),\n    )\n    self.gracefully_stop()\n    try:\n        async with asyncio.timeout(self._stopping_grace_period):\n            await self.wait_for_exit()\n        await self.on_shutdown()\n        return\n    except asyncio.TimeoutError:\n        logger.warning(\n            \"could not stop workers %s gracefully after %s\"\n            \" seconds - force shutdown\",\n            \", \".join(\n                task.get_name() for task in self._workers.tasks if not task.done()\n            ),\n            self._stopping_grace_period,\n        )\n    except asyncio.CancelledError:\n        pass\n    self._force_shutdown = True\n    self._workers.cancel()\n    try:\n        await self.wait_for_exit()\n    except asyncio.CancelledError:\n        pass\n    await self.on_shutdown()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.bail_out","title":"bail_out","text":"
    bail_out(reason, code=1)\n
    Source code in fluid/utils/worker.py
    def bail_out(self, reason: str, code: int = 1) -> None:\n    self.gracefully_stop()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.safe_run","title":"safe_run async","text":"
    safe_run()\n

    Context manager to run a worker safely

    Source code in fluid/utils/worker.py
    @asynccontextmanager\nasync def safe_run(self) -> AsyncGenerator:\n    \"\"\"Context manager to run a worker safely\"\"\"\n    try:\n        yield\n    except asyncio.CancelledError:\n        if self._force_shutdown:\n            # we are shutting down, this is expected\n            pass\n        raise\n    except Exception as e:\n        reason = f\"unhandled exception while running workers: {e}\"\n        logger.exception(reason)\n        asyncio.get_event_loop().call_soon(self.bail_out, reason, 2)\n    else:\n        # worker finished without error\n        # make sure we are shutting down\n        asyncio.get_event_loop().call_soon(self.bail_out, \"worker exit\", 1)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.remove_workers","title":"remove_workers","text":"
    remove_workers(*workers)\n

    remove workers from the workers

    Source code in fluid/utils/worker.py
    def remove_workers(self, *workers: Worker) -> None:\n    \"remove workers from the workers\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        try:\n            workers_.remove(worker)\n        except ValueError:\n            pass\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.startup","title":"startup async","text":"
    startup()\n

    start the workers

    Source code in fluid/utils/worker.py
    async def startup(self) -> None:\n    \"\"\"start the workers\"\"\"\n    if self._workers_task is None:\n        self._workers_task = asyncio.create_task(self.run(), name=self.worker_name)\n        for args in self._delayed_callbacks:\n            self._delayed_callback(*args)\n        self._delayed_callbacks = []\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_callback","title":"register_callback","text":"
    register_callback(\n    callback, seconds, jitter=0.0, periodic=False\n)\n

    Register a callback

    The callback can be periodic or not.

    Source code in fluid/utils/worker.py
    def register_callback(\n    self,\n    callback: Callable[[], None],\n    seconds: float,\n    jitter: float = 0.0,\n    periodic: bool | float = False,\n) -> None:\n    \"\"\"Register a callback\n\n    The callback can be periodic or not.\n    \"\"\"\n    if periodic is True:\n        periodic_float = seconds\n    elif periodic is False:\n        periodic_float = 0.0\n    else:\n        periodic_float = periodic\n    if not self.running:\n        self._delayed_callbacks.append((callback, seconds, jitter, periodic_float))\n    else:\n        self._delayed_callback(callback, seconds, jitter, periodic_float)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.enter_async_context","title":"enter_async_context async","text":"
    enter_async_context(cm)\n
    Source code in fluid/scheduler/consumer.py
    async def enter_async_context(self, cm: Any) -> Any:\n    return await self._stack.enter_async_context(cm)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.execute","title":"execute async","text":"
    execute(task, **params)\n

    Execute a task and wait for it to finish

    Source code in fluid/scheduler/consumer.py
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:\n    \"\"\"Execute a task and wait for it to finish\"\"\"\n    task_run = self.create_task_run(task, **params)\n    await task_run.execute()\n    return task_run\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.execute_sync","title":"execute_sync","text":"
    execute_sync(task, **params)\n
    Source code in fluid/scheduler/consumer.py
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:\n    return asyncio.run(self._execute_and_exit(task, **params))\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_task","title":"register_task","text":"
    register_task(task)\n

    Register a task with the task manager

    Only tasks registered can be executed by a task manager

    Source code in fluid/scheduler/consumer.py
    def register_task(self, task: Task) -> None:\n    \"\"\"Register a task with the task manager\n\n    Only tasks registered can be executed by a task manager\n    \"\"\"\n    self.broker.register_task(task)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.queue","title":"queue async","text":"
    queue(task, priority=None, **params)\n

    Queue a task for execution

    This methods fires two events:

    • queue: when the task is about to be queued
    • queued: after the task is queued
    Source code in fluid/scheduler/consumer.py
    async def queue(\n    self,\n    task: str | Task,\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Queue a task for execution\n\n    This methods fires two events:\n\n    - queue: when the task is about to be queued\n    - queued: after the task is queued\n    \"\"\"\n    task_run = self.create_task_run(task, priority=priority, **params)\n    self.dispatcher.dispatch(task_run)\n    task_run.set_state(TaskState.queued)\n    await self.broker.queue_task(task_run)\n    return task_run\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.create_task_run","title":"create_task_run","text":"
    create_task_run(task, run_id='', priority=None, **params)\n

    Create a TaskRun in init state

    Source code in fluid/scheduler/consumer.py
    def create_task_run(\n    self,\n    task: str | Task,\n    run_id: str = \"\",\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Create a TaskRun in `init` state\"\"\"\n    if isinstance(task, str):\n        task = self.broker.task_from_registry(task)\n    run_id = run_id or self.broker.new_uuid()\n    return TaskRun(\n        id=run_id,\n        task=task,\n        priority=priority or task.priority,\n        params=params,\n        task_manager=self,\n    )\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_from_module","title":"register_from_module","text":"
    register_from_module(module)\n
    Source code in fluid/scheduler/consumer.py
    def register_from_module(self, module: Any) -> None:\n    for name in dir(module):\n        if name.startswith(\"_\"):\n            continue\n        if isinstance(obj := getattr(module, name), Task):\n            self.register_task(obj)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.cli","title":"cli","text":"
    cli(**kwargs)\n

    Create the task manager command line interface

    Source code in fluid/scheduler/consumer.py
    def cli(self, **kwargs: Any) -> Any:\n    \"\"\"Create the task manager command line interface\"\"\"\n    try:\n        from fluid.scheduler.cli import TaskManagerCLI\n    except ImportError:\n        raise ImportError(\n            \"TaskManagerCLI is not available - \"\n            \"install with `pip install aio-fluid[cli]`\"\n        ) from None\n    return TaskManagerCLI(self, **kwargs)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.sync_queue","title":"sync_queue","text":"
    sync_queue(task)\n
    Source code in fluid/scheduler/consumer.py
    def sync_queue(self, task: str | Task) -> None:\n    self._task_to_queue.appendleft(task)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.sync_priority_queue","title":"sync_priority_queue","text":"
    sync_priority_queue(task)\n
    Source code in fluid/scheduler/consumer.py
    def sync_priority_queue(self, task: str | Task) -> None:\n    self._priority_task_run_queue.appendleft(self.create_task_run(task))\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.num_concurrent_tasks_for","title":"num_concurrent_tasks_for","text":"
    num_concurrent_tasks_for(task_name)\n

    The number of concurrent tasks for a given task_name

    Source code in fluid/scheduler/consumer.py
    def num_concurrent_tasks_for(self, task_name: str) -> int:\n    \"\"\"The number of concurrent tasks for a given task_name\"\"\"\n    return len(self._concurrent_tasks[task_name])\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.queue_and_wait","title":"queue_and_wait async","text":"
    queue_and_wait(task, *, timeout=2, **params)\n

    Queue a task and wait for it to finish

    Source code in fluid/scheduler/consumer.py
    async def queue_and_wait(\n    self, task: str, *, timeout: int = 2, **params: Any\n) -> TaskRun:\n    \"\"\"Queue a task and wait for it to finish\"\"\"\n    with TaskRunWaiter(self) as waiter:\n        return await waiter.wait(await self.queue(task, **params), timeout=timeout)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_async_handler","title":"register_async_handler","text":"
    register_async_handler(event, handler)\n
    Source code in fluid/scheduler/consumer.py
    def register_async_handler(self, event: Event | str, handler: AsyncHandler) -> None:\n    event = Event.from_string_or_event(event)\n    self.dispatcher.register_handler(\n        f\"{event.type}.async_dispatch\",\n        self._async_dispatcher_worker.send,\n    )\n    self._async_dispatcher_worker.dispatcher.register_handler(event, handler)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.unregister_async_handler","title":"unregister_async_handler","text":"
    unregister_async_handler(event)\n
    Source code in fluid/scheduler/consumer.py
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:\n    return self._async_dispatcher_worker.dispatcher.unregister_handler(event)\n
    "},{"location":"reference/workers/","title":"Workers","text":"

    Workers are the main building block for asynchronous programming with aio-fluid. They are responsible for running tasks and managing their lifecycle. There are several worker classes which can be imported from fluid.utils.worker:

    from fastapi.utils.worker import StoppingWorker\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker","title":"fluid.utils.worker.Worker","text":"
    Worker(name='')\n

    Bases: ABC

    The base class of a worker that can be run

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    self._name: str = name or underscore(type(self).__name__)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.Worker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.Worker.status","title":"status abstractmethod async","text":"
    status()\n

    Get the status of the worker.

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def status(self) -> dict:\n    \"\"\"\n    Get the status of the worker.\n    \"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.gracefully_stop","title":"gracefully_stop abstractmethod","text":"
    gracefully_stop()\n

    gracefully stop the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef gracefully_stop(self) -> None:\n    \"gracefully stop the worker\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.is_running","title":"is_running abstractmethod","text":"
    is_running()\n

    Is the worker running?

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef is_running(self) -> bool:\n    \"\"\"Is the worker running?\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.is_stopping","title":"is_stopping abstractmethod","text":"
    is_stopping()\n

    Is the worker stopping?

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef is_stopping(self) -> bool:\n    \"\"\"Is the worker stopping?\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker","title":"fluid.utils.worker.RunningWorker","text":"
    RunningWorker(name='')\n

    Bases: Worker

    A Worker that can be started

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    super().__init__(name)\n    self._running: bool = False\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.status","title":"status abstractmethod async","text":"
    status()\n

    Get the status of the worker.

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def status(self) -> dict:\n    \"\"\"\n    Get the status of the worker.\n    \"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.gracefully_stop","title":"gracefully_stop abstractmethod","text":"
    gracefully_stop()\n

    gracefully stop the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef gracefully_stop(self) -> None:\n    \"gracefully stop the worker\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.is_stopping","title":"is_stopping abstractmethod","text":"
    is_stopping()\n

    Is the worker stopping?

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef is_stopping(self) -> bool:\n    \"\"\"Is the worker stopping?\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker","title":"fluid.utils.worker.StoppingWorker","text":"
    StoppingWorker(name='')\n

    Bases: RunningWorker

    A Worker that can be stopped

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    super().__init__(name)\n    self._stopping: bool = False\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return {\"stopping\": self.is_stopping(), \"running\": self.is_running()}\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction","title":"fluid.utils.worker.WorkerFunction","text":"
    WorkerFunction(run_function, heartbeat=0, name='')\n

    Bases: StoppingWorker

    A Worker that runs a coroutine function

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    run_function: Callable[[], Awaitable[None]],\n    heartbeat: float | int = 0,\n    name: str = \"\",\n) -> None:\n    super().__init__(name=name)\n    self._run_function = run_function\n    self._heartbeat = heartbeat\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return {\"stopping\": self.is_stopping(), \"running\": self.is_running()}\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            await self._run_function()\n            await asyncio.sleep(self._heartbeat)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer","title":"fluid.utils.worker.QueueConsumer","text":"
    QueueConsumer(name='')\n

    Bases: StoppingWorker, MessageProducer[MessageType]

    A Worker that can receive messages

    This worker can receive messages but not consume them.

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    super().__init__(name=name)\n    self._queue: asyncio.Queue[MessageType | None] = asyncio.Queue()\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.get_message","title":"get_message async","text":"
    get_message(timeout=0.5)\n
    Source code in fluid/utils/worker.py
    async def get_message(self, timeout: float = 0.5) -> MessageType | None:\n    try:\n        async with asyncio.timeout(timeout):\n            return await self._queue.get()\n    except asyncio.TimeoutError:\n        return None\n    except (asyncio.CancelledError, RuntimeError):\n        if not self.is_stopping():\n            raise\n    return None\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.queue_size","title":"queue_size","text":"
    queue_size()\n
    Source code in fluid/utils/worker.py
    def queue_size(self) -> int:\n    return self._queue.qsize()\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    status = await super().status()\n    status.update(queue_size=self.queue_size())\n    return status\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.send","title":"send","text":"
    send(message)\n

    Send a message into the worker

    Source code in fluid/utils/worker.py
    def send(self, message: MessageType | None) -> None:\n    \"\"\"Send a message into the worker\"\"\"\n    self._queue.put_nowait(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker","title":"fluid.utils.worker.QueueConsumerWorker","text":"
    QueueConsumerWorker(on_message, name='')\n

    Bases: QueueConsumer[MessageType]

    A Worker that can receive and consume messages

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    on_message: Callable[[MessageType], Awaitable[None]],\n    name: str = \"\",\n) -> None:\n    super().__init__(name=name)\n    self.on_message = on_message\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.on_message","title":"on_message instance-attribute","text":"
    on_message = on_message\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.send","title":"send","text":"
    send(message)\n

    Send a message into the worker

    Source code in fluid/utils/worker.py
    def send(self, message: MessageType | None) -> None:\n    \"\"\"Send a message into the worker\"\"\"\n    self._queue.put_nowait(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    status = await super().status()\n    status.update(queue_size=self.queue_size())\n    return status\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.get_message","title":"get_message async","text":"
    get_message(timeout=0.5)\n
    Source code in fluid/utils/worker.py
    async def get_message(self, timeout: float = 0.5) -> MessageType | None:\n    try:\n        async with asyncio.timeout(timeout):\n            return await self._queue.get()\n    except asyncio.TimeoutError:\n        return None\n    except (asyncio.CancelledError, RuntimeError):\n        if not self.is_stopping():\n            raise\n    return None\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.queue_size","title":"queue_size","text":"
    queue_size()\n
    Source code in fluid/utils/worker.py
    def queue_size(self) -> int:\n    return self._queue.qsize()\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            message = await self.get_message()\n            if message is not None:\n                await self.on_message(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer","title":"fluid.utils.worker.AsyncConsumer","text":"
    AsyncConsumer(dispatcher, name='')\n

    Bases: QueueConsumer[MessageType]

    A Worker that can dispatch async callbacks

    Source code in fluid/utils/worker.py
    def __init__(\n    self, dispatcher: AsyncDispatcher[MessageType], name: str = \"\"\n) -> None:\n    super().__init__(name)\n    self.dispatcher: AsyncDispatcher[MessageType] = dispatcher\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.AsyncCallback","title":"AsyncCallback instance-attribute","text":"
    AsyncCallback\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.dispatcher","title":"dispatcher instance-attribute","text":"
    dispatcher = dispatcher\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.send","title":"send","text":"
    send(message)\n

    Send a message into the worker

    Source code in fluid/utils/worker.py
    def send(self, message: MessageType | None) -> None:\n    \"\"\"Send a message into the worker\"\"\"\n    self._queue.put_nowait(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    status = await super().status()\n    status.update(queue_size=self.queue_size())\n    return status\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.get_message","title":"get_message async","text":"
    get_message(timeout=0.5)\n
    Source code in fluid/utils/worker.py
    async def get_message(self, timeout: float = 0.5) -> MessageType | None:\n    try:\n        async with asyncio.timeout(timeout):\n            return await self._queue.get()\n    except asyncio.TimeoutError:\n        return None\n    except (asyncio.CancelledError, RuntimeError):\n        if not self.is_stopping():\n            raise\n    return None\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.queue_size","title":"queue_size","text":"
    queue_size()\n
    Source code in fluid/utils/worker.py
    def queue_size(self) -> int:\n    return self._queue.qsize()\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            message = await self.get_message()\n            if message is not None:\n                await self.dispatcher.dispatch(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers","title":"fluid.utils.worker.Workers","text":"
    Workers(\n    *workers,\n    name=\"\",\n    stopping_grace_period=STOPPING_GRACE_PERIOD\n)\n

    Bases: MultipleWorkers

    A worker managing several workers

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    *workers: Worker,\n    name: str = \"\",\n    stopping_grace_period: int = settings.STOPPING_GRACE_PERIOD,\n) -> None:\n    super().__init__(\n        *workers, name=name, stopping_grace_period=stopping_grace_period\n    )\n    self._workers_task: asyncio.Task | None = None\n    self._delayed_callbacks: list[\n        tuple[Callable[[], None], float, float, float]\n    ] = []\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.Workers.num_workers","title":"num_workers property","text":"
    num_workers\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.running","title":"running property","text":"
    running\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return await self._workers.status()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._workers.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._workers.is_stopping()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.create_task","title":"create_task","text":"
    create_task(worker)\n
    Source code in fluid/utils/worker.py
    def create_task(self, worker: Worker) -> asyncio.Task:\n    return asyncio.create_task(\n        self._run_worker(worker), name=f\"{self.worker_name}-{worker.worker_name}\"\n    )\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n

    called after the workers are stopped

    Source code in fluid/utils/worker.py
    async def on_shutdown(self) -> None:\n    \"\"\"called after the workers are stopped\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.shutdown","title":"shutdown async","text":"
    shutdown()\n

    shutdown the workers

    Source code in fluid/utils/worker.py
    async def shutdown(self) -> None:\n    \"\"\"shutdown the workers\"\"\"\n    if self._has_shutdown:\n        return\n    self._has_shutdown = True\n    logger.warning(\n        \"gracefully stopping %d workers: %s\",\n        self.num_workers,\n        \", \".join(w.worker_name for w in self._workers.workers),\n    )\n    self.gracefully_stop()\n    try:\n        async with asyncio.timeout(self._stopping_grace_period):\n            await self.wait_for_exit()\n        await self.on_shutdown()\n        return\n    except asyncio.TimeoutError:\n        logger.warning(\n            \"could not stop workers %s gracefully after %s\"\n            \" seconds - force shutdown\",\n            \", \".join(\n                task.get_name() for task in self._workers.tasks if not task.done()\n            ),\n            self._stopping_grace_period,\n        )\n    except asyncio.CancelledError:\n        pass\n    self._force_shutdown = True\n    self._workers.cancel()\n    try:\n        await self.wait_for_exit()\n    except asyncio.CancelledError:\n        pass\n    await self.on_shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.bail_out","title":"bail_out","text":"
    bail_out(reason, code=1)\n
    Source code in fluid/utils/worker.py
    def bail_out(self, reason: str, code: int = 1) -> None:\n    self.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.safe_run","title":"safe_run async","text":"
    safe_run()\n

    Context manager to run a worker safely

    Source code in fluid/utils/worker.py
    @asynccontextmanager\nasync def safe_run(self) -> AsyncGenerator:\n    \"\"\"Context manager to run a worker safely\"\"\"\n    try:\n        yield\n    except asyncio.CancelledError:\n        if self._force_shutdown:\n            # we are shutting down, this is expected\n            pass\n        raise\n    except Exception as e:\n        reason = f\"unhandled exception while running workers: {e}\"\n        logger.exception(reason)\n        asyncio.get_event_loop().call_soon(self.bail_out, reason, 2)\n    else:\n        # worker finished without error\n        # make sure we are shutting down\n        asyncio.get_event_loop().call_soon(self.bail_out, \"worker exit\", 1)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.add_workers","title":"add_workers","text":"
    add_workers(*workers)\n

    add workers to the workers

    Source code in fluid/utils/worker.py
    def add_workers(self, *workers: Worker) -> None:\n    \"\"\"add workers to the workers\"\"\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        if worker not in workers_:\n            workers_.append(worker)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.run","title":"run async","text":"
    run()\n

    run the workers

    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    \"\"\"run the workers\"\"\"\n    with self.start_running():\n        async with self.safe_run():\n            workers, _ = self._workers.workers_tasks()\n            self._workers.workers = tuple(workers)\n            self._workers.tasks = tuple(\n                self.create_task(worker) for worker in workers\n            )\n            await asyncio.gather(*self._workers.tasks)\n        await self.shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.wait_for_exit","title":"wait_for_exit async","text":"
    wait_for_exit()\n
    Source code in fluid/utils/worker.py
    async def wait_for_exit(self) -> None:\n    if self._workers_task is not None:\n        await self._workers_task\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.remove_workers","title":"remove_workers","text":"
    remove_workers(*workers)\n

    remove workers from the workers

    Source code in fluid/utils/worker.py
    def remove_workers(self, *workers: Worker) -> None:\n    \"remove workers from the workers\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        try:\n            workers_.remove(worker)\n        except ValueError:\n            pass\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.startup","title":"startup async","text":"
    startup()\n

    start the workers

    Source code in fluid/utils/worker.py
    async def startup(self) -> None:\n    \"\"\"start the workers\"\"\"\n    if self._workers_task is None:\n        self._workers_task = asyncio.create_task(self.run(), name=self.worker_name)\n        for args in self._delayed_callbacks:\n            self._delayed_callback(*args)\n        self._delayed_callbacks = []\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.register_callback","title":"register_callback","text":"
    register_callback(\n    callback, seconds, jitter=0.0, periodic=False\n)\n

    Register a callback

    The callback can be periodic or not.

    Source code in fluid/utils/worker.py
    def register_callback(\n    self,\n    callback: Callable[[], None],\n    seconds: float,\n    jitter: float = 0.0,\n    periodic: bool | float = False,\n) -> None:\n    \"\"\"Register a callback\n\n    The callback can be periodic or not.\n    \"\"\"\n    if periodic is True:\n        periodic_float = seconds\n    elif periodic is False:\n        periodic_float = 0.0\n    else:\n        periodic_float = periodic\n    if not self.running:\n        self._delayed_callbacks.append((callback, seconds, jitter, periodic_float))\n    else:\n        self._delayed_callback(callback, seconds, jitter, periodic_float)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers","title":"fluid.utils.worker.DynamicWorkers","text":"
    DynamicWorkers(\n    *workers,\n    name=\"\",\n    heartbeat=0.1,\n    stopping_grace_period=STOPPING_GRACE_PERIOD\n)\n

    Bases: MultipleWorkers

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    *workers: Worker,\n    name: str = \"\",\n    heartbeat: float | int = 0.1,\n    stopping_grace_period: int = settings.STOPPING_GRACE_PERIOD,\n) -> None:\n    super().__init__(name)\n    self._heartbeat = heartbeat\n    self._workers = WorkerTasks()\n    self._has_shutdown = False\n    self._force_shutdown = False\n    self._stopping_grace_period = stopping_grace_period\n    self.add_workers(*workers)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.num_workers","title":"num_workers property","text":"
    num_workers\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return await self._workers.status()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._workers.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._workers.is_stopping()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.create_task","title":"create_task","text":"
    create_task(worker)\n
    Source code in fluid/utils/worker.py
    def create_task(self, worker: Worker) -> asyncio.Task:\n    return asyncio.create_task(\n        self._run_worker(worker), name=f\"{self.worker_name}-{worker.worker_name}\"\n    )\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n

    called after the workers are stopped

    Source code in fluid/utils/worker.py
    async def on_shutdown(self) -> None:\n    \"\"\"called after the workers are stopped\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.shutdown","title":"shutdown async","text":"
    shutdown()\n

    shutdown the workers

    Source code in fluid/utils/worker.py
    async def shutdown(self) -> None:\n    \"\"\"shutdown the workers\"\"\"\n    if self._has_shutdown:\n        return\n    self._has_shutdown = True\n    logger.warning(\n        \"gracefully stopping %d workers: %s\",\n        self.num_workers,\n        \", \".join(w.worker_name for w in self._workers.workers),\n    )\n    self.gracefully_stop()\n    try:\n        async with asyncio.timeout(self._stopping_grace_period):\n            await self.wait_for_exit()\n        await self.on_shutdown()\n        return\n    except asyncio.TimeoutError:\n        logger.warning(\n            \"could not stop workers %s gracefully after %s\"\n            \" seconds - force shutdown\",\n            \", \".join(\n                task.get_name() for task in self._workers.tasks if not task.done()\n            ),\n            self._stopping_grace_period,\n        )\n    except asyncio.CancelledError:\n        pass\n    self._force_shutdown = True\n    self._workers.cancel()\n    try:\n        await self.wait_for_exit()\n    except asyncio.CancelledError:\n        pass\n    await self.on_shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.bail_out","title":"bail_out","text":"
    bail_out(reason, code=1)\n
    Source code in fluid/utils/worker.py
    def bail_out(self, reason: str, code: int = 1) -> None:\n    self.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.safe_run","title":"safe_run async","text":"
    safe_run()\n

    Context manager to run a worker safely

    Source code in fluid/utils/worker.py
    @asynccontextmanager\nasync def safe_run(self) -> AsyncGenerator:\n    \"\"\"Context manager to run a worker safely\"\"\"\n    try:\n        yield\n    except asyncio.CancelledError:\n        if self._force_shutdown:\n            # we are shutting down, this is expected\n            pass\n        raise\n    except Exception as e:\n        reason = f\"unhandled exception while running workers: {e}\"\n        logger.exception(reason)\n        asyncio.get_event_loop().call_soon(self.bail_out, reason, 2)\n    else:\n        # worker finished without error\n        # make sure we are shutting down\n        asyncio.get_event_loop().call_soon(self.bail_out, \"worker exit\", 1)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.add_workers","title":"add_workers","text":"
    add_workers(*workers)\n

    add workers to the workers

    They can be added while the workers are running.

    Source code in fluid/utils/worker.py
    def add_workers(self, *workers: Worker) -> None:\n    \"\"\"add workers to the workers\n\n    They can be added while the workers are running.\n    \"\"\"\n    workers_, tasks_ = self._workers.workers_tasks()\n    for worker in workers:\n        workers_.append(worker)\n        tasks_.append(self.create_task(worker))\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            for worker, task in zip(self._workers.workers, self._workers.tasks):\n                if worker.is_stopping() or task.done():\n                    break\n            await asyncio.sleep(self._heartbeat)\n        await self.shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.wait_for_exit","title":"wait_for_exit async","text":"
    wait_for_exit()\n
    Source code in fluid/utils/worker.py
    async def wait_for_exit(self) -> None:\n    await asyncio.gather(*self._workers.tasks)\n
    "},{"location":"tutorials/","title":"Tutorials","text":"

    The step-by-step guides, the how-to's, the recipes, and all the Aio Fluid parts you can use in your applications.

    "},{"location":"tutorials/db/","title":"Async Database","text":"

    The fluid.db module provides a simple asynchronous interface to interact with postgres databases. It is built on top of the sqlalchemy and asyncpg libraries.

    "},{"location":"tutorials/dispatchers/","title":"Event Dispatchers","text":"

    Event dispatchers are a way to decouple the event source from the event handler. This is useful when you want to have multiple handlers for the same event, or when you want to have a single handler for multiple events.

    from fluid.utils.dispatcher import SimpleDispatcher\n\nsimple = SimpleDispatcher[Any]()\n\nsimple.dispatch(\"you can dispatch anything to this generic dispatcher\")\n
    "},{"location":"tutorials/scheduler/","title":"Task Queue","text":"

    This module has a lightweight implementation of a distributed task producer (TaskScheduler) and consumer (TaskConsumer). The middleware for distributing tasks can be configured via the Broker interface. A redis broker is provided for convenience.

    "},{"location":"tutorials/scheduler/#tasks","title":"Tasks","text":"

    Tasks are standard python async functions decorated with the task decorator.

    from fluid.scheduler import task, TaskRun\n\n@task\nasync def say_hi(ctx: TaskRun):\n    return \"Hi!\"\n

    There are two types of tasks implemented

    • Simple concurrent tasks - they run concurrently with the task consumer - thy must be IO type tasks (no heavy CPU bound operations)
      from fluid.scheduler import task, TaskRun\n\n  @task\n  async def fecth_data(ctx: TaskRun):\n      # fetch data\n      data = await http_cli.get(\"https://...\")\n      data_id = await datastore_cli.stote(data)\n      # trigger another task\n      ctx.task_manager.queue(\"heavy_calculation\", data_id=data_id)\n
    • CPU bound tasks - they run on a subprocess
    from fluid.scheduler import task, TaskRun\n\n@task(cpu_bound=True)\nasync def heavy_calculation(ctx: TaskRun):\n    data = await datastore_cli.get(ctx.params[\"data_id\"])\n    # perform some heavy calculation\n    ...\n    # trigger another task\n    ctx.task_manager.queue(\"fetch_data\")\n

    Both tasks can be periodically scheduled via the schedule keyword argument:

    from datetime import timedelta\nfrom fluid.scheduler import task, TaskContext, every\n\n@task(schedule=every(timedelta(seconds=1)))\nasync def scheduled(context: TaskContext) -> str:\n    await asyncio.sleep(0.1)\n    return \"OK\"\n
    "},{"location":"tutorials/scheduler/#broker","title":"Broker","text":"

    A Task broker needs to implement three abstract methods

      @abstractmethod\n  async def queue_task(self, queued_task: QueuedTask) -> TaskRun:\n      \"\"\"Queue a task\"\"\"\n\n  @abstractmethod\n  async def get_task_run(self) -> Optional[TaskRun]:\n      \"\"\"Get a Task run from the task queue\"\"\"\n\n  @abstractmethod\n  async def queue_length(self) -> Dict[str, int]:\n      \"\"\"Length of task queues\"\"\"\n

    The library ships a Redis broker for convenience.

    from fluid.scheduler import Broker\n\nredis_broker = Broker.from_url(\"redis://localhost:6349\")\n
    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"

    Aio Fluid

    Async utilities for backend python services developed by Quantmind.

    Documentation: https://quantmind.github.io/aio-fluid

    Source Code: https://github.com/quantmind/aio-fluid

    "},{"location":"#installation","title":"Installation","text":"

    This is a simple python package you can install via pip:

    pip install aio-fluid\n

    To install all the dependencies:

    pip install aio-fluid[cli, db, http, log]\n
    this includes the following extra dependencies:

    • cli for the command line interface using click and rich
    • db for database support with asyncpg and sqlalchemy
    • http for http client support with httpx and aiohttp
    • log for JSON logging support with python-json-logger
    "},{"location":"#development","title":"Development","text":"

    You can run the examples via

    poetry run python -m examples.main\n
    "},{"location":"reference/","title":"Introduction","text":"

    Here's the reference or code API, the classes, functions, parameters, attributes, and all the aio-fluid parts you can use in your applications.

    "},{"location":"reference/dispatchers/","title":"Event Dispatchers","text":"

    A set of classes for dispatching events, they can be imported from fluid.utils.dispatcher:

    from fluid.utils.dispatcher import Dispatcher\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher","title":"fluid.utils.dispatcher.BaseDispatcher","text":"
    BaseDispatcher()\n

    Bases: Generic[MessageType, MessageHandlerType], ABC

    Source code in fluid/utils/dispatcher.py
    def __init__(self) -> None:\n    self._msg_handlers: defaultdict[str, dict[str, MessageHandlerType]] = (\n        defaultdict(\n            dict,\n        )\n    )\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.register_handler","title":"register_handler","text":"
    register_handler(event, handler)\n
    Source code in fluid/utils/dispatcher.py
    def register_handler(\n    self,\n    event: Event | str,\n    handler: MessageHandlerType,\n) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    previous = self._msg_handlers[event.type].get(event.tag)\n    self._msg_handlers[event.type][event.tag] = handler\n    return previous\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.unregister_handler","title":"unregister_handler","text":"
    unregister_handler(event)\n
    Source code in fluid/utils/dispatcher.py
    def unregister_handler(self, event: Event | str) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    return self._msg_handlers[event.type].pop(event.tag, None)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.get_handlers","title":"get_handlers","text":"
    get_handlers(message)\n
    Source code in fluid/utils/dispatcher.py
    def get_handlers(\n    self,\n    message: MessageType,\n) -> dict[str, MessageHandlerType] | None:\n    message_type = str(self.message_type(message))\n    return self._msg_handlers.get(message_type)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.BaseDispatcher.message_type","title":"message_type abstractmethod","text":"
    message_type(message)\n

    return the message type

    Source code in fluid/utils/dispatcher.py
    @abstractmethod\ndef message_type(self, message: MessageType) -> str:\n    \"\"\"return the message type\"\"\"\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher","title":"fluid.utils.dispatcher.Dispatcher","text":"
    Dispatcher()\n

    Bases: BaseDispatcher[MessageType, Callable[[MessageType], None]]

    Dispatcher for sync handlers

    Source code in fluid/utils/dispatcher.py
    def __init__(self) -> None:\n    self._msg_handlers: defaultdict[str, dict[str, MessageHandlerType]] = (\n        defaultdict(\n            dict,\n        )\n    )\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.register_handler","title":"register_handler","text":"
    register_handler(event, handler)\n
    Source code in fluid/utils/dispatcher.py
    def register_handler(\n    self,\n    event: Event | str,\n    handler: MessageHandlerType,\n) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    previous = self._msg_handlers[event.type].get(event.tag)\n    self._msg_handlers[event.type][event.tag] = handler\n    return previous\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.unregister_handler","title":"unregister_handler","text":"
    unregister_handler(event)\n
    Source code in fluid/utils/dispatcher.py
    def unregister_handler(self, event: Event | str) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    return self._msg_handlers[event.type].pop(event.tag, None)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.get_handlers","title":"get_handlers","text":"
    get_handlers(message)\n
    Source code in fluid/utils/dispatcher.py
    def get_handlers(\n    self,\n    message: MessageType,\n) -> dict[str, MessageHandlerType] | None:\n    message_type = str(self.message_type(message))\n    return self._msg_handlers.get(message_type)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.message_type","title":"message_type abstractmethod","text":"
    message_type(message)\n

    return the message type

    Source code in fluid/utils/dispatcher.py
    @abstractmethod\ndef message_type(self, message: MessageType) -> str:\n    \"\"\"return the message type\"\"\"\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.Dispatcher.dispatch","title":"dispatch","text":"
    dispatch(message)\n

    dispatch the message

    Source code in fluid/utils/dispatcher.py
    def dispatch(self, message: MessageType) -> int:\n    \"\"\"dispatch the message\"\"\"\n    handlers = self.get_handlers(message)\n    if handlers:\n        for handler in handlers.values():\n            handler(message)\n    return len(handlers or ())\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher","title":"fluid.utils.dispatcher.AsyncDispatcher","text":"
    AsyncDispatcher()\n

    Bases: BaseDispatcher[MessageType, Callable[[MessageType], Awaitable[None]]]

    Dispatcher for async handlers

    Source code in fluid/utils/dispatcher.py
    def __init__(self) -> None:\n    self._msg_handlers: defaultdict[str, dict[str, MessageHandlerType]] = (\n        defaultdict(\n            dict,\n        )\n    )\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.register_handler","title":"register_handler","text":"
    register_handler(event, handler)\n
    Source code in fluid/utils/dispatcher.py
    def register_handler(\n    self,\n    event: Event | str,\n    handler: MessageHandlerType,\n) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    previous = self._msg_handlers[event.type].get(event.tag)\n    self._msg_handlers[event.type][event.tag] = handler\n    return previous\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.unregister_handler","title":"unregister_handler","text":"
    unregister_handler(event)\n
    Source code in fluid/utils/dispatcher.py
    def unregister_handler(self, event: Event | str) -> MessageHandlerType | None:\n    event = Event.from_string_or_event(event)\n    return self._msg_handlers[event.type].pop(event.tag, None)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.get_handlers","title":"get_handlers","text":"
    get_handlers(message)\n
    Source code in fluid/utils/dispatcher.py
    def get_handlers(\n    self,\n    message: MessageType,\n) -> dict[str, MessageHandlerType] | None:\n    message_type = str(self.message_type(message))\n    return self._msg_handlers.get(message_type)\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.message_type","title":"message_type abstractmethod","text":"
    message_type(message)\n

    return the message type

    Source code in fluid/utils/dispatcher.py
    @abstractmethod\ndef message_type(self, message: MessageType) -> str:\n    \"\"\"return the message type\"\"\"\n
    "},{"location":"reference/dispatchers/#fluid.utils.dispatcher.AsyncDispatcher.dispatch","title":"dispatch async","text":"
    dispatch(message)\n

    Dispatch the message and wait for all handlers to complete

    Source code in fluid/utils/dispatcher.py
    async def dispatch(self, message: MessageType) -> int:\n    \"\"\"Dispatch the message and wait for all handlers to complete\"\"\"\n    handlers = self.get_handlers(message)\n    if handlers:\n        await asyncio.gather(*[handler(message) for handler in handlers.values()])\n    return len(handlers or ())\n
    "},{"location":"reference/task_broker/","title":"Task Broker","text":"

    It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskBroker\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker","title":"fluid.scheduler.TaskBroker","text":"
    TaskBroker(url)\n

    Bases: ABC

    Source code in fluid/scheduler/broker.py
    def __init__(self, url: URL) -> None:\n    self.url: URL = url\n    self.registry: TaskRegistry = TaskRegistry()\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.url","title":"url instance-attribute","text":"
    url = url\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.registry","title":"registry instance-attribute","text":"
    registry = TaskRegistry()\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.task_queue_names","title":"task_queue_names abstractmethod property","text":"
    task_queue_names\n

    Names of the task queues

    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.queue_task","title":"queue_task abstractmethod async","text":"
    queue_task(task_run)\n

    Queue a task

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def queue_task(self, task_run: TaskRun) -> None:\n    \"\"\"Queue a task\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.get_task_run","title":"get_task_run abstractmethod async","text":"
    get_task_run(task_manager)\n

    Get a Task run from the task queue

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def get_task_run(self, task_manager: TaskManager) -> TaskRun | None:\n    \"\"\"Get a Task run from the task queue\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.queue_length","title":"queue_length abstractmethod async","text":"
    queue_length()\n

    Length of task queues

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def queue_length(self) -> dict[str, int]:\n    \"\"\"Length of task queues\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.get_tasks_info","title":"get_tasks_info abstractmethod async","text":"
    get_tasks_info(*task_names)\n

    List of TaskInfo objects

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def get_tasks_info(self, *task_names: str) -> list[TaskInfo]:\n    \"\"\"List of TaskInfo objects\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.update_task","title":"update_task abstractmethod async","text":"
    update_task(task, params)\n

    Update a task dynamic parameters

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def update_task(self, task: Task, params: dict[str, Any]) -> TaskInfo:\n    \"\"\"Update a task dynamic parameters\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.close","title":"close abstractmethod async","text":"
    close()\n

    Close the broker on shutdown

    Source code in fluid/scheduler/broker.py
    @abstractmethod\nasync def close(self) -> None:\n    \"\"\"Close the broker on shutdown\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.lock","title":"lock abstractmethod","text":"
    lock(name, timeout=None)\n

    Create a lock

    Source code in fluid/scheduler/broker.py
    @abstractmethod\ndef lock(self, name: str, timeout: float | None = None) -> Lock:\n    \"\"\"Create a lock\"\"\"\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.new_uuid","title":"new_uuid","text":"
    new_uuid()\n
    Source code in fluid/scheduler/broker.py
    def new_uuid(self) -> str:\n    return uuid4().hex\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.filter_tasks","title":"filter_tasks async","text":"
    filter_tasks(scheduled=None, enabled=None)\n
    Source code in fluid/scheduler/broker.py
    async def filter_tasks(\n    self,\n    scheduled: bool | None = None,\n    enabled: bool | None = None,\n) -> list[Task]:\n    task_info = await self.get_tasks_info()\n    task_map = {info.name: info for info in task_info}\n    tasks = []\n    for task in self.registry.values():\n        if scheduled is not None and bool(task.schedule) is not scheduled:\n            continue\n        if enabled is not None and task_map[task.name].enabled is not enabled:\n            continue\n        tasks.append(task)\n    return tasks\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.task_from_registry","title":"task_from_registry","text":"
    task_from_registry(task)\n
    Source code in fluid/scheduler/broker.py
    def task_from_registry(self, task: str | Task) -> Task:\n    if isinstance(task, Task):\n        self.register_task(task)\n        return task\n    else:\n        if task_ := self.registry.get(task):\n            return task_\n        raise UnknownTaskError(task)\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.register_task","title":"register_task","text":"
    register_task(task)\n
    Source code in fluid/scheduler/broker.py
    def register_task(self, task: Task) -> None:\n    self.registry[task.name] = task\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.enable_task","title":"enable_task async","text":"
    enable_task(task_name, enable=True)\n

    Enable or disable a registered task

    Source code in fluid/scheduler/broker.py
    async def enable_task(self, task_name: str, enable: bool = True) -> TaskInfo:\n    \"\"\"Enable or disable a registered task\"\"\"\n    task = self.registry.get(task_name)\n    if not task:\n        raise UnknownTaskError(task_name)\n    return await self.update_task(task, dict(enabled=enable))\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.from_url","title":"from_url classmethod","text":"
    from_url(url='')\n
    Source code in fluid/scheduler/broker.py
    @classmethod\ndef from_url(cls, url: str = \"\") -> TaskBroker:\n    p = URL(url or broker_url_from_env())\n    if factory := _brokers.get(p.scheme):\n        return factory(p)\n    raise RuntimeError(f\"Invalid broker {p}\")\n
    "},{"location":"reference/task_broker/#fluid.scheduler.TaskBroker.register_broker","title":"register_broker classmethod","text":"
    register_broker(name, factory)\n
    Source code in fluid/scheduler/broker.py
    @classmethod\ndef register_broker(cls, name: str, factory: type[TaskBroker]) -> None:\n    _brokers[name] = factory\n
    "},{"location":"reference/task_manager/","title":"Task Manager","text":"

    It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskManager\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager","title":"fluid.scheduler.TaskManager","text":"
    TaskManager(**kwargs)\n

    The task manager is the main entry point for managing tasks

    Source code in fluid/scheduler/consumer.py
    def __init__(self, **kwargs: Any) -> None:\n    self.state: dict[str, Any] = {}\n    self.config: TaskManagerConfig = TaskManagerConfig(**kwargs)\n    self.dispatcher: Annotated[\n        TaskDispatcher,\n        Doc(\n            \"\"\"\n            A dispatcher of task run events.\n\n            Register handlers to listen for task run events.\n            \"\"\"\n        ),\n    ] = TaskDispatcher()\n    self.broker = TaskBroker.from_url(self.config.broker_url)\n    self._stack = AsyncExitStack()\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.state","title":"state instance-attribute","text":"
    state = {}\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.config","title":"config instance-attribute","text":"
    config = TaskManagerConfig(**kwargs)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.dispatcher","title":"dispatcher instance-attribute","text":"
    dispatcher = TaskDispatcher()\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.broker","title":"broker instance-attribute","text":"
    broker = from_url(broker_url)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.registry","title":"registry property","text":"
    registry\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.type","title":"type property","text":"
    type\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.enter_async_context","title":"enter_async_context async","text":"
    enter_async_context(cm)\n
    Source code in fluid/scheduler/consumer.py
    async def enter_async_context(self, cm: Any) -> Any:\n    return await self._stack.enter_async_context(cm)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.execute","title":"execute async","text":"
    execute(task, **params)\n

    Execute a task and wait for it to finish

    Source code in fluid/scheduler/consumer.py
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:\n    \"\"\"Execute a task and wait for it to finish\"\"\"\n    task_run = self.create_task_run(task, **params)\n    await task_run.execute()\n    return task_run\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n
    Source code in fluid/scheduler/consumer.py
    async def on_shutdown(self) -> None:\n    await self.broker.close()\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.execute_sync","title":"execute_sync","text":"
    execute_sync(task, **params)\n
    Source code in fluid/scheduler/consumer.py
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:\n    return asyncio.run(self._execute_and_exit(task, **params))\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.register_task","title":"register_task","text":"
    register_task(task)\n

    Register a task with the task manager

    Only tasks registered can be executed by a task manager

    Source code in fluid/scheduler/consumer.py
    def register_task(self, task: Task) -> None:\n    \"\"\"Register a task with the task manager\n\n    Only tasks registered can be executed by a task manager\n    \"\"\"\n    self.broker.register_task(task)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.queue","title":"queue async","text":"
    queue(task, priority=None, **params)\n

    Queue a task for execution

    This methods fires two events:

    • queue: when the task is about to be queued
    • queued: after the task is queued
    Source code in fluid/scheduler/consumer.py
    async def queue(\n    self,\n    task: str | Task,\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Queue a task for execution\n\n    This methods fires two events:\n\n    - queue: when the task is about to be queued\n    - queued: after the task is queued\n    \"\"\"\n    task_run = self.create_task_run(task, priority=priority, **params)\n    self.dispatcher.dispatch(task_run)\n    task_run.set_state(TaskState.queued)\n    await self.broker.queue_task(task_run)\n    return task_run\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.create_task_run","title":"create_task_run","text":"
    create_task_run(task, run_id='', priority=None, **params)\n

    Create a TaskRun in init state

    Source code in fluid/scheduler/consumer.py
    def create_task_run(\n    self,\n    task: str | Task,\n    run_id: str = \"\",\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Create a TaskRun in `init` state\"\"\"\n    if isinstance(task, str):\n        task = self.broker.task_from_registry(task)\n    run_id = run_id or self.broker.new_uuid()\n    return TaskRun(\n        id=run_id,\n        task=task,\n        priority=priority or task.priority,\n        params=params,\n        task_manager=self,\n    )\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.register_from_module","title":"register_from_module","text":"
    register_from_module(module)\n
    Source code in fluid/scheduler/consumer.py
    def register_from_module(self, module: Any) -> None:\n    for name in dir(module):\n        if name.startswith(\"_\"):\n            continue\n        if isinstance(obj := getattr(module, name), Task):\n            self.register_task(obj)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.register_from_dict","title":"register_from_dict","text":"
    register_from_dict(data)\n
    Source code in fluid/scheduler/consumer.py
    def register_from_dict(self, data: dict) -> None:\n    for name, obj in data.items():\n        if name.startswith(\"_\"):\n            continue\n        if isinstance(obj, Task):\n            self.register_task(obj)\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.register_async_handler","title":"register_async_handler","text":"
    register_async_handler(event, handler)\n

    Register an async handler for a given event

    This method is a no op for a TaskManager that is not a worker

    Source code in fluid/scheduler/consumer.py
    def register_async_handler(self, event: str, handler: AsyncHandler) -> None:\n    \"\"\"Register an async handler for a given event\n\n    This method is a no op for a TaskManager that is not a worker\n    \"\"\"\n
    "},{"location":"reference/task_manager/#fluid.scheduler.TaskManager.unregister_async_handler","title":"unregister_async_handler","text":"
    unregister_async_handler(event)\n

    Unregister an async handler for a given event

    This method is a no op for a TaskManager that is not a worker

    Source code in fluid/scheduler/consumer.py
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:\n    \"\"\"Unregister an async handler for a given event\n\n    This method is a no op for a TaskManager that is not a worker\n    \"\"\"\n    return None\n
    "},{"location":"reference/task_run/","title":"Task Run","text":"

    It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskRun\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun","title":"fluid.scheduler.TaskRun","text":"

    Bases: BaseModel

    A TaskRun contains all the data generated by a Task run

    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.id","title":"id instance-attribute","text":"
    id\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.task","title":"task instance-attribute","text":"
    task\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.priority","title":"priority instance-attribute","text":"
    priority\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.params","title":"params instance-attribute","text":"
    params\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.state","title":"state class-attribute instance-attribute","text":"
    state = init\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.task_manager","title":"task_manager class-attribute instance-attribute","text":"
    task_manager = Field(exclude=True, repr=False)\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.queued","title":"queued class-attribute instance-attribute","text":"
    queued = None\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.start","title":"start class-attribute instance-attribute","text":"
    start = None\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.end","title":"end class-attribute instance-attribute","text":"
    end = None\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.logger","title":"logger property","text":"
    logger\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.in_queue","title":"in_queue property","text":"
    in_queue\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.duration","title":"duration property","text":"
    duration\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.duration_ms","title":"duration_ms property","text":"
    duration_ms\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.total","title":"total property","text":"
    total\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.name","title":"name property","text":"
    name\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.name_id","title":"name_id property","text":"
    name_id\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.is_done","title":"is_done property","text":"
    is_done\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.is_failure","title":"is_failure property","text":"
    is_failure\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.execute","title":"execute async","text":"
    execute()\n
    Source code in fluid/scheduler/models.py
    async def execute(self) -> None:\n    try:\n        self.set_state(TaskState.running)\n        await self.task.executor(self)\n    except Exception:\n        self.set_state(TaskState.failure)\n        raise\n    else:\n        self.set_state(TaskState.success)\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.serialize_task","title":"serialize_task","text":"
    serialize_task(task, _info)\n
    Source code in fluid/scheduler/models.py
    @field_serializer(\"task\")\ndef serialize_task(self, task: Task, _info: Any) -> str:\n    return task.name\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.params_dump_json","title":"params_dump_json","text":"
    params_dump_json()\n
    Source code in fluid/scheduler/models.py
    def params_dump_json(self) -> str:\n    return self.task.params_dump_json(self.params)\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.set_state","title":"set_state","text":"
    set_state(state, state_time=None)\n
    Source code in fluid/scheduler/models.py
    def set_state(\n    self,\n    state: TaskState,\n    state_time: datetime | None = None,\n) -> None:\n    if self.state == state:\n        return\n    state_time = as_utc(state_time)\n    match (self.state, state):\n        case (TaskState.init, TaskState.queued):\n            self.queued = state_time\n            self.state = state\n            self._dispatch()\n        case (TaskState.init, _):\n            self.set_state(TaskState.queued, state_time)\n            self.set_state(state, state_time)\n        case (TaskState.queued, TaskState.running):\n            self.start = state_time\n            self.state = state\n            self._dispatch()\n        case (\n            TaskState.queued,\n            TaskState.success\n            | TaskState.aborted\n            | TaskState.rate_limited\n            | TaskState.failure,\n        ):\n            self.set_state(TaskState.running, state_time)\n            self.set_state(state, state_time)\n        case (\n            TaskState.running,\n            TaskState.success\n            | TaskState.aborted\n            | TaskState.rate_limited\n            | TaskState.failure,\n        ):\n            self.end = state_time\n            self.state = state\n            self._dispatch()\n        case _:\n            raise TaskRunError(f\"invalid state transition {self.state} -> {state}\")\n
    "},{"location":"reference/task_run/#fluid.scheduler.TaskRun.lock","title":"lock","text":"
    lock(timeout)\n
    Source code in fluid/scheduler/models.py
    def lock(self, timeout: float | None) -> Lock:\n    return self.task_manager.broker.lock(self.name, timeout=timeout)\n
    "},{"location":"reference/tast_consumer/","title":"Task Consumer","text":"

    The task consumer is a TaskManager which is also a Workers that consumes tasks from the task queue and executes them. It can be imported from fluid.scheduler:

    from fastapi.scheduler import TaskConsumer\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer","title":"fluid.scheduler.TaskConsumer","text":"
    TaskConsumer(**config)\n

    Bases: TaskManager, Workers

    The Task Consumer is a Task Manager responsible for consuming tasks from a task queue

    Source code in fluid/scheduler/consumer.py
    def __init__(self, **config: Any) -> None:\n    super().__init__(**config)\n    Workers.__init__(self)\n    self._async_dispatcher_worker = AsyncConsumer(AsyncTaskDispatcher())\n    self._concurrent_tasks: dict[str, dict[str, TaskRun]] = defaultdict(dict)\n    self._task_to_queue: deque[str | Task] = deque()\n    self._priority_task_run_queue: deque[TaskRun] = deque()\n    self._queue_tasks_worker = WorkerFunction(\n        self._queue_task, name=\"queue-task-worker\"\n    )\n    self.add_workers(self._queue_tasks_worker)\n    self.add_workers(self._async_dispatcher_worker)\n    for i in range(self.config.max_concurrent_tasks):\n        worker_name = f\"task-worker-{i+1}\"\n        self.add_workers(\n            WorkerFunction(\n                partial(self._consume_tasks, worker_name), name=worker_name\n            )\n        )\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.num_workers","title":"num_workers property","text":"
    num_workers\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.running","title":"running property","text":"
    running\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.state","title":"state instance-attribute","text":"
    state = {}\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.config","title":"config instance-attribute","text":"
    config = TaskManagerConfig(**kwargs)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.dispatcher","title":"dispatcher instance-attribute","text":"
    dispatcher = TaskDispatcher()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.broker","title":"broker instance-attribute","text":"
    broker = from_url(broker_url)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.registry","title":"registry property","text":"
    registry\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.type","title":"type property","text":"
    type\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.num_concurrent_tasks","title":"num_concurrent_tasks property","text":"
    num_concurrent_tasks\n

    The number of concurrent_tasks running in the consumer

    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return await self._workers.status()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._workers.gracefully_stop()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._workers.is_stopping()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.run","title":"run async","text":"
    run()\n

    run the workers

    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    \"\"\"run the workers\"\"\"\n    with self.start_running():\n        async with self.safe_run():\n            workers, _ = self._workers.workers_tasks()\n            self._workers.workers = tuple(workers)\n            self._workers.tasks = tuple(\n                self.create_task(worker) for worker in workers\n            )\n            await asyncio.gather(*self._workers.tasks)\n        await self.shutdown()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.add_workers","title":"add_workers","text":"
    add_workers(*workers)\n

    add workers to the workers

    Source code in fluid/utils/worker.py
    def add_workers(self, *workers: Worker) -> None:\n    \"\"\"add workers to the workers\"\"\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        if worker not in workers_:\n            workers_.append(worker)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.wait_for_exit","title":"wait_for_exit async","text":"
    wait_for_exit()\n
    Source code in fluid/utils/worker.py
    async def wait_for_exit(self) -> None:\n    if self._workers_task is not None:\n        await self._workers_task\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.create_task","title":"create_task","text":"
    create_task(worker)\n
    Source code in fluid/utils/worker.py
    def create_task(self, worker: Worker) -> asyncio.Task:\n    return asyncio.create_task(\n        self._run_worker(worker), name=f\"{self.worker_name}-{worker.worker_name}\"\n    )\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n
    Source code in fluid/scheduler/consumer.py
    async def on_shutdown(self) -> None:\n    await self.broker.close()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.shutdown","title":"shutdown async","text":"
    shutdown()\n

    shutdown the workers

    Source code in fluid/utils/worker.py
    async def shutdown(self) -> None:\n    \"\"\"shutdown the workers\"\"\"\n    if self._has_shutdown:\n        return\n    self._has_shutdown = True\n    logger.warning(\n        \"gracefully stopping %d workers: %s\",\n        self.num_workers,\n        \", \".join(w.worker_name for w in self._workers.workers),\n    )\n    self.gracefully_stop()\n    try:\n        async with asyncio.timeout(self._stopping_grace_period):\n            await self.wait_for_exit()\n        await self.on_shutdown()\n        return\n    except asyncio.TimeoutError:\n        logger.warning(\n            \"could not stop workers %s gracefully after %s\"\n            \" seconds - force shutdown\",\n            \", \".join(\n                task.get_name() for task in self._workers.tasks if not task.done()\n            ),\n            self._stopping_grace_period,\n        )\n    except asyncio.CancelledError:\n        pass\n    self._force_shutdown = True\n    self._workers.cancel()\n    try:\n        await self.wait_for_exit()\n    except asyncio.CancelledError:\n        pass\n    await self.on_shutdown()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.bail_out","title":"bail_out","text":"
    bail_out(reason, code=1)\n
    Source code in fluid/utils/worker.py
    def bail_out(self, reason: str, code: int = 1) -> None:\n    self.gracefully_stop()\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.safe_run","title":"safe_run async","text":"
    safe_run()\n

    Context manager to run a worker safely

    Source code in fluid/utils/worker.py
    @asynccontextmanager\nasync def safe_run(self) -> AsyncGenerator:\n    \"\"\"Context manager to run a worker safely\"\"\"\n    try:\n        yield\n    except asyncio.CancelledError:\n        if self._force_shutdown:\n            # we are shutting down, this is expected\n            pass\n        raise\n    except Exception as e:\n        reason = f\"unhandled exception while running workers: {e}\"\n        logger.exception(reason)\n        asyncio.get_event_loop().call_soon(self.bail_out, reason, 2)\n    else:\n        # worker finished without error\n        # make sure we are shutting down\n        asyncio.get_event_loop().call_soon(self.bail_out, \"worker exit\", 1)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.remove_workers","title":"remove_workers","text":"
    remove_workers(*workers)\n

    remove workers from the workers

    Source code in fluid/utils/worker.py
    def remove_workers(self, *workers: Worker) -> None:\n    \"remove workers from the workers\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        try:\n            workers_.remove(worker)\n        except ValueError:\n            pass\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.startup","title":"startup async","text":"
    startup()\n

    start the workers

    Source code in fluid/utils/worker.py
    async def startup(self) -> None:\n    \"\"\"start the workers\"\"\"\n    if self._workers_task is None:\n        self._workers_task = asyncio.create_task(self.run(), name=self.worker_name)\n        for args in self._delayed_callbacks:\n            self._delayed_callback(*args)\n        self._delayed_callbacks = []\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_callback","title":"register_callback","text":"
    register_callback(\n    callback, seconds, jitter=0.0, periodic=False\n)\n

    Register a callback

    The callback can be periodic or not.

    Source code in fluid/utils/worker.py
    def register_callback(\n    self,\n    callback: Callable[[], None],\n    seconds: float,\n    jitter: float = 0.0,\n    periodic: bool | float = False,\n) -> None:\n    \"\"\"Register a callback\n\n    The callback can be periodic or not.\n    \"\"\"\n    if periodic is True:\n        periodic_float = seconds\n    elif periodic is False:\n        periodic_float = 0.0\n    else:\n        periodic_float = periodic\n    if not self.running:\n        self._delayed_callbacks.append((callback, seconds, jitter, periodic_float))\n    else:\n        self._delayed_callback(callback, seconds, jitter, periodic_float)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.enter_async_context","title":"enter_async_context async","text":"
    enter_async_context(cm)\n
    Source code in fluid/scheduler/consumer.py
    async def enter_async_context(self, cm: Any) -> Any:\n    return await self._stack.enter_async_context(cm)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.execute","title":"execute async","text":"
    execute(task, **params)\n

    Execute a task and wait for it to finish

    Source code in fluid/scheduler/consumer.py
    async def execute(self, task: Task | str, **params: Any) -> TaskRun:\n    \"\"\"Execute a task and wait for it to finish\"\"\"\n    task_run = self.create_task_run(task, **params)\n    await task_run.execute()\n    return task_run\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.execute_sync","title":"execute_sync","text":"
    execute_sync(task, **params)\n
    Source code in fluid/scheduler/consumer.py
    def execute_sync(self, task: Task | str, **params: Any) -> TaskRun:\n    return asyncio.run(self._execute_and_exit(task, **params))\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_task","title":"register_task","text":"
    register_task(task)\n

    Register a task with the task manager

    Only tasks registered can be executed by a task manager

    Source code in fluid/scheduler/consumer.py
    def register_task(self, task: Task) -> None:\n    \"\"\"Register a task with the task manager\n\n    Only tasks registered can be executed by a task manager\n    \"\"\"\n    self.broker.register_task(task)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.queue","title":"queue async","text":"
    queue(task, priority=None, **params)\n

    Queue a task for execution

    This methods fires two events:

    • queue: when the task is about to be queued
    • queued: after the task is queued
    Source code in fluid/scheduler/consumer.py
    async def queue(\n    self,\n    task: str | Task,\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Queue a task for execution\n\n    This methods fires two events:\n\n    - queue: when the task is about to be queued\n    - queued: after the task is queued\n    \"\"\"\n    task_run = self.create_task_run(task, priority=priority, **params)\n    self.dispatcher.dispatch(task_run)\n    task_run.set_state(TaskState.queued)\n    await self.broker.queue_task(task_run)\n    return task_run\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.create_task_run","title":"create_task_run","text":"
    create_task_run(task, run_id='', priority=None, **params)\n

    Create a TaskRun in init state

    Source code in fluid/scheduler/consumer.py
    def create_task_run(\n    self,\n    task: str | Task,\n    run_id: str = \"\",\n    priority: TaskPriority | None = None,\n    **params: Any,\n) -> TaskRun:\n    \"\"\"Create a TaskRun in `init` state\"\"\"\n    if isinstance(task, str):\n        task = self.broker.task_from_registry(task)\n    run_id = run_id or self.broker.new_uuid()\n    return TaskRun(\n        id=run_id,\n        task=task,\n        priority=priority or task.priority,\n        params=params,\n        task_manager=self,\n    )\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_from_module","title":"register_from_module","text":"
    register_from_module(module)\n
    Source code in fluid/scheduler/consumer.py
    def register_from_module(self, module: Any) -> None:\n    for name in dir(module):\n        if name.startswith(\"_\"):\n            continue\n        if isinstance(obj := getattr(module, name), Task):\n            self.register_task(obj)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_from_dict","title":"register_from_dict","text":"
    register_from_dict(data)\n
    Source code in fluid/scheduler/consumer.py
    def register_from_dict(self, data: dict) -> None:\n    for name, obj in data.items():\n        if name.startswith(\"_\"):\n            continue\n        if isinstance(obj, Task):\n            self.register_task(obj)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.sync_queue","title":"sync_queue","text":"
    sync_queue(task)\n
    Source code in fluid/scheduler/consumer.py
    def sync_queue(self, task: str | Task) -> None:\n    self._task_to_queue.appendleft(task)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.sync_priority_queue","title":"sync_priority_queue","text":"
    sync_priority_queue(task)\n
    Source code in fluid/scheduler/consumer.py
    def sync_priority_queue(self, task: str | Task) -> None:\n    self._priority_task_run_queue.appendleft(self.create_task_run(task))\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.num_concurrent_tasks_for","title":"num_concurrent_tasks_for","text":"
    num_concurrent_tasks_for(task_name)\n

    The number of concurrent tasks for a given task_name

    Source code in fluid/scheduler/consumer.py
    def num_concurrent_tasks_for(self, task_name: str) -> int:\n    \"\"\"The number of concurrent tasks for a given task_name\"\"\"\n    return len(self._concurrent_tasks[task_name])\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.queue_and_wait","title":"queue_and_wait async","text":"
    queue_and_wait(task, *, timeout=2, **params)\n

    Queue a task and wait for it to finish

    Source code in fluid/scheduler/consumer.py
    async def queue_and_wait(\n    self, task: str, *, timeout: int = 2, **params: Any\n) -> TaskRun:\n    \"\"\"Queue a task and wait for it to finish\"\"\"\n    with TaskRunWaiter(self) as waiter:\n        return await waiter.wait(await self.queue(task, **params), timeout=timeout)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.register_async_handler","title":"register_async_handler","text":"
    register_async_handler(event, handler)\n
    Source code in fluid/scheduler/consumer.py
    def register_async_handler(self, event: Event | str, handler: AsyncHandler) -> None:\n    event = Event.from_string_or_event(event)\n    self.dispatcher.register_handler(\n        f\"{event.type}.async_dispatch\",\n        self._async_dispatcher_worker.send,\n    )\n    self._async_dispatcher_worker.dispatcher.register_handler(event, handler)\n
    "},{"location":"reference/tast_consumer/#fluid.scheduler.TaskConsumer.unregister_async_handler","title":"unregister_async_handler","text":"
    unregister_async_handler(event)\n
    Source code in fluid/scheduler/consumer.py
    def unregister_async_handler(self, event: Event | str) -> AsyncHandler | None:\n    return self._async_dispatcher_worker.dispatcher.unregister_handler(event)\n
    "},{"location":"reference/workers/","title":"Workers","text":"

    Workers are the main building block for asynchronous programming with aio-fluid. They are responsible for running tasks and managing their lifecycle. There are several worker classes which can be imported from fluid.utils.worker:

    from fastapi.utils.worker import StoppingWorker\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker","title":"fluid.utils.worker.Worker","text":"
    Worker(name='')\n

    Bases: ABC

    The base class of a worker that can be run

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    self._name: str = name or underscore(type(self).__name__)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.Worker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.Worker.status","title":"status abstractmethod async","text":"
    status()\n

    Get the status of the worker.

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def status(self) -> dict:\n    \"\"\"\n    Get the status of the worker.\n    \"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.gracefully_stop","title":"gracefully_stop abstractmethod","text":"
    gracefully_stop()\n

    gracefully stop the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef gracefully_stop(self) -> None:\n    \"gracefully stop the worker\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.is_running","title":"is_running abstractmethod","text":"
    is_running()\n

    Is the worker running?

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef is_running(self) -> bool:\n    \"\"\"Is the worker running?\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.is_stopping","title":"is_stopping abstractmethod","text":"
    is_stopping()\n

    Is the worker stopping?

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef is_stopping(self) -> bool:\n    \"\"\"Is the worker stopping?\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Worker.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker","title":"fluid.utils.worker.RunningWorker","text":"
    RunningWorker(name='')\n

    Bases: Worker

    A Worker that can be started

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    super().__init__(name)\n    self._running: bool = False\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.status","title":"status abstractmethod async","text":"
    status()\n

    Get the status of the worker.

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def status(self) -> dict:\n    \"\"\"\n    Get the status of the worker.\n    \"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.gracefully_stop","title":"gracefully_stop abstractmethod","text":"
    gracefully_stop()\n

    gracefully stop the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef gracefully_stop(self) -> None:\n    \"gracefully stop the worker\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.is_stopping","title":"is_stopping abstractmethod","text":"
    is_stopping()\n

    Is the worker stopping?

    Source code in fluid/utils/worker.py
    @abstractmethod\ndef is_stopping(self) -> bool:\n    \"\"\"Is the worker stopping?\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.RunningWorker.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker","title":"fluid.utils.worker.StoppingWorker","text":"
    StoppingWorker(name='')\n

    Bases: RunningWorker

    A Worker that can be stopped

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    super().__init__(name)\n    self._stopping: bool = False\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.StoppingWorker.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return {\"stopping\": self.is_stopping(), \"running\": self.is_running()}\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction","title":"fluid.utils.worker.WorkerFunction","text":"
    WorkerFunction(run_function, heartbeat=0, name='')\n

    Bases: StoppingWorker

    A Worker that runs a coroutine function

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    run_function: Callable[[], Awaitable[None]],\n    heartbeat: float | int = 0,\n    name: str = \"\",\n) -> None:\n    super().__init__(name=name)\n    self._run_function = run_function\n    self._heartbeat = heartbeat\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return {\"stopping\": self.is_stopping(), \"running\": self.is_running()}\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.WorkerFunction.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            await self._run_function()\n            await asyncio.sleep(self._heartbeat)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer","title":"fluid.utils.worker.QueueConsumer","text":"
    QueueConsumer(name='')\n

    Bases: StoppingWorker, MessageProducer[MessageType]

    A Worker that can receive messages

    This worker can receive messages but not consume them.

    Source code in fluid/utils/worker.py
    def __init__(self, name: str = \"\") -> None:\n    super().__init__(name=name)\n    self._queue: asyncio.Queue[MessageType | None] = asyncio.Queue()\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.run","title":"run abstractmethod async","text":"
    run()\n

    run the worker

    Source code in fluid/utils/worker.py
    @abstractmethod\nasync def run(self) -> None:\n    \"\"\"run the worker\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.get_message","title":"get_message async","text":"
    get_message(timeout=0.5)\n
    Source code in fluid/utils/worker.py
    async def get_message(self, timeout: float = 0.5) -> MessageType | None:\n    try:\n        async with asyncio.timeout(timeout):\n            return await self._queue.get()\n    except asyncio.TimeoutError:\n        return None\n    except (asyncio.CancelledError, RuntimeError):\n        if not self.is_stopping():\n            raise\n    return None\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.queue_size","title":"queue_size","text":"
    queue_size()\n
    Source code in fluid/utils/worker.py
    def queue_size(self) -> int:\n    return self._queue.qsize()\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    status = await super().status()\n    status.update(queue_size=self.queue_size())\n    return status\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumer.send","title":"send","text":"
    send(message)\n

    Send a message into the worker

    Source code in fluid/utils/worker.py
    def send(self, message: MessageType | None) -> None:\n    \"\"\"Send a message into the worker\"\"\"\n    self._queue.put_nowait(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker","title":"fluid.utils.worker.QueueConsumerWorker","text":"
    QueueConsumerWorker(on_message, name='')\n

    Bases: QueueConsumer[MessageType]

    A Worker that can receive and consume messages

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    on_message: Callable[[MessageType], Awaitable[None]],\n    name: str = \"\",\n) -> None:\n    super().__init__(name=name)\n    self.on_message = on_message\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.on_message","title":"on_message instance-attribute","text":"
    on_message = on_message\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.send","title":"send","text":"
    send(message)\n

    Send a message into the worker

    Source code in fluid/utils/worker.py
    def send(self, message: MessageType | None) -> None:\n    \"\"\"Send a message into the worker\"\"\"\n    self._queue.put_nowait(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    status = await super().status()\n    status.update(queue_size=self.queue_size())\n    return status\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.get_message","title":"get_message async","text":"
    get_message(timeout=0.5)\n
    Source code in fluid/utils/worker.py
    async def get_message(self, timeout: float = 0.5) -> MessageType | None:\n    try:\n        async with asyncio.timeout(timeout):\n            return await self._queue.get()\n    except asyncio.TimeoutError:\n        return None\n    except (asyncio.CancelledError, RuntimeError):\n        if not self.is_stopping():\n            raise\n    return None\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.queue_size","title":"queue_size","text":"
    queue_size()\n
    Source code in fluid/utils/worker.py
    def queue_size(self) -> int:\n    return self._queue.qsize()\n
    "},{"location":"reference/workers/#fluid.utils.worker.QueueConsumerWorker.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            message = await self.get_message()\n            if message is not None:\n                await self.on_message(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer","title":"fluid.utils.worker.AsyncConsumer","text":"
    AsyncConsumer(dispatcher, name='')\n

    Bases: QueueConsumer[MessageType]

    A Worker that can dispatch async callbacks

    Source code in fluid/utils/worker.py
    def __init__(\n    self, dispatcher: AsyncDispatcher[MessageType], name: str = \"\"\n) -> None:\n    super().__init__(name)\n    self.dispatcher: AsyncDispatcher[MessageType] = dispatcher\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.num_workers","title":"num_workers property","text":"
    num_workers\n

    The number of workers in this worker

    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.AsyncCallback","title":"AsyncCallback instance-attribute","text":"
    AsyncCallback\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.dispatcher","title":"dispatcher instance-attribute","text":"
    dispatcher = dispatcher\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.send","title":"send","text":"
    send(message)\n

    Send a message into the worker

    Source code in fluid/utils/worker.py
    def send(self, message: MessageType | None) -> None:\n    \"\"\"Send a message into the worker\"\"\"\n    self._queue.put_nowait(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    status = await super().status()\n    status.update(queue_size=self.queue_size())\n    return status\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._stopping = True\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._stopping\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.get_message","title":"get_message async","text":"
    get_message(timeout=0.5)\n
    Source code in fluid/utils/worker.py
    async def get_message(self, timeout: float = 0.5) -> MessageType | None:\n    try:\n        async with asyncio.timeout(timeout):\n            return await self._queue.get()\n    except asyncio.TimeoutError:\n        return None\n    except (asyncio.CancelledError, RuntimeError):\n        if not self.is_stopping():\n            raise\n    return None\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.queue_size","title":"queue_size","text":"
    queue_size()\n
    Source code in fluid/utils/worker.py
    def queue_size(self) -> int:\n    return self._queue.qsize()\n
    "},{"location":"reference/workers/#fluid.utils.worker.AsyncConsumer.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            message = await self.get_message()\n            if message is not None:\n                await self.dispatcher.dispatch(message)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers","title":"fluid.utils.worker.Workers","text":"
    Workers(\n    *workers,\n    name=\"\",\n    stopping_grace_period=STOPPING_GRACE_PERIOD\n)\n

    Bases: MultipleWorkers

    A worker managing several workers

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    *workers: Worker,\n    name: str = \"\",\n    stopping_grace_period: int = settings.STOPPING_GRACE_PERIOD,\n) -> None:\n    super().__init__(\n        *workers, name=name, stopping_grace_period=stopping_grace_period\n    )\n    self._workers_task: asyncio.Task | None = None\n    self._delayed_callbacks: list[\n        tuple[Callable[[], None], float, float, float]\n    ] = []\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.Workers.num_workers","title":"num_workers property","text":"
    num_workers\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.running","title":"running property","text":"
    running\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return await self._workers.status()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._workers.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._workers.is_stopping()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.create_task","title":"create_task","text":"
    create_task(worker)\n
    Source code in fluid/utils/worker.py
    def create_task(self, worker: Worker) -> asyncio.Task:\n    return asyncio.create_task(\n        self._run_worker(worker), name=f\"{self.worker_name}-{worker.worker_name}\"\n    )\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n

    called after the workers are stopped

    Source code in fluid/utils/worker.py
    async def on_shutdown(self) -> None:\n    \"\"\"called after the workers are stopped\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.shutdown","title":"shutdown async","text":"
    shutdown()\n

    shutdown the workers

    Source code in fluid/utils/worker.py
    async def shutdown(self) -> None:\n    \"\"\"shutdown the workers\"\"\"\n    if self._has_shutdown:\n        return\n    self._has_shutdown = True\n    logger.warning(\n        \"gracefully stopping %d workers: %s\",\n        self.num_workers,\n        \", \".join(w.worker_name for w in self._workers.workers),\n    )\n    self.gracefully_stop()\n    try:\n        async with asyncio.timeout(self._stopping_grace_period):\n            await self.wait_for_exit()\n        await self.on_shutdown()\n        return\n    except asyncio.TimeoutError:\n        logger.warning(\n            \"could not stop workers %s gracefully after %s\"\n            \" seconds - force shutdown\",\n            \", \".join(\n                task.get_name() for task in self._workers.tasks if not task.done()\n            ),\n            self._stopping_grace_period,\n        )\n    except asyncio.CancelledError:\n        pass\n    self._force_shutdown = True\n    self._workers.cancel()\n    try:\n        await self.wait_for_exit()\n    except asyncio.CancelledError:\n        pass\n    await self.on_shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.bail_out","title":"bail_out","text":"
    bail_out(reason, code=1)\n
    Source code in fluid/utils/worker.py
    def bail_out(self, reason: str, code: int = 1) -> None:\n    self.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.safe_run","title":"safe_run async","text":"
    safe_run()\n

    Context manager to run a worker safely

    Source code in fluid/utils/worker.py
    @asynccontextmanager\nasync def safe_run(self) -> AsyncGenerator:\n    \"\"\"Context manager to run a worker safely\"\"\"\n    try:\n        yield\n    except asyncio.CancelledError:\n        if self._force_shutdown:\n            # we are shutting down, this is expected\n            pass\n        raise\n    except Exception as e:\n        reason = f\"unhandled exception while running workers: {e}\"\n        logger.exception(reason)\n        asyncio.get_event_loop().call_soon(self.bail_out, reason, 2)\n    else:\n        # worker finished without error\n        # make sure we are shutting down\n        asyncio.get_event_loop().call_soon(self.bail_out, \"worker exit\", 1)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.add_workers","title":"add_workers","text":"
    add_workers(*workers)\n

    add workers to the workers

    Source code in fluid/utils/worker.py
    def add_workers(self, *workers: Worker) -> None:\n    \"\"\"add workers to the workers\"\"\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        if worker not in workers_:\n            workers_.append(worker)\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.run","title":"run async","text":"
    run()\n

    run the workers

    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    \"\"\"run the workers\"\"\"\n    with self.start_running():\n        async with self.safe_run():\n            workers, _ = self._workers.workers_tasks()\n            self._workers.workers = tuple(workers)\n            self._workers.tasks = tuple(\n                self.create_task(worker) for worker in workers\n            )\n            await asyncio.gather(*self._workers.tasks)\n        await self.shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.wait_for_exit","title":"wait_for_exit async","text":"
    wait_for_exit()\n
    Source code in fluid/utils/worker.py
    async def wait_for_exit(self) -> None:\n    if self._workers_task is not None:\n        await self._workers_task\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.remove_workers","title":"remove_workers","text":"
    remove_workers(*workers)\n

    remove workers from the workers

    Source code in fluid/utils/worker.py
    def remove_workers(self, *workers: Worker) -> None:\n    \"remove workers from the workers\"\n    workers_, _ = self._workers.workers_tasks()\n    for worker in workers:\n        try:\n            workers_.remove(worker)\n        except ValueError:\n            pass\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.startup","title":"startup async","text":"
    startup()\n

    start the workers

    Source code in fluid/utils/worker.py
    async def startup(self) -> None:\n    \"\"\"start the workers\"\"\"\n    if self._workers_task is None:\n        self._workers_task = asyncio.create_task(self.run(), name=self.worker_name)\n        for args in self._delayed_callbacks:\n            self._delayed_callback(*args)\n        self._delayed_callbacks = []\n
    "},{"location":"reference/workers/#fluid.utils.worker.Workers.register_callback","title":"register_callback","text":"
    register_callback(\n    callback, seconds, jitter=0.0, periodic=False\n)\n

    Register a callback

    The callback can be periodic or not.

    Source code in fluid/utils/worker.py
    def register_callback(\n    self,\n    callback: Callable[[], None],\n    seconds: float,\n    jitter: float = 0.0,\n    periodic: bool | float = False,\n) -> None:\n    \"\"\"Register a callback\n\n    The callback can be periodic or not.\n    \"\"\"\n    if periodic is True:\n        periodic_float = seconds\n    elif periodic is False:\n        periodic_float = 0.0\n    else:\n        periodic_float = periodic\n    if not self.running:\n        self._delayed_callbacks.append((callback, seconds, jitter, periodic_float))\n    else:\n        self._delayed_callback(callback, seconds, jitter, periodic_float)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers","title":"fluid.utils.worker.DynamicWorkers","text":"
    DynamicWorkers(\n    *workers,\n    name=\"\",\n    heartbeat=0.1,\n    stopping_grace_period=STOPPING_GRACE_PERIOD\n)\n

    Bases: MultipleWorkers

    Source code in fluid/utils/worker.py
    def __init__(\n    self,\n    *workers: Worker,\n    name: str = \"\",\n    heartbeat: float | int = 0.1,\n    stopping_grace_period: int = settings.STOPPING_GRACE_PERIOD,\n) -> None:\n    super().__init__(name)\n    self._heartbeat = heartbeat\n    self._workers = WorkerTasks()\n    self._has_shutdown = False\n    self._force_shutdown = False\n    self._stopping_grace_period = stopping_grace_period\n    self.add_workers(*workers)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.worker_name","title":"worker_name property","text":"
    worker_name\n

    The name of the worker

    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.num_workers","title":"num_workers property","text":"
    num_workers\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.status","title":"status async","text":"
    status()\n
    Source code in fluid/utils/worker.py
    async def status(self) -> dict:\n    return await self._workers.status()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.gracefully_stop","title":"gracefully_stop","text":"
    gracefully_stop()\n
    Source code in fluid/utils/worker.py
    def gracefully_stop(self) -> None:\n    self._workers.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.is_running","title":"is_running","text":"
    is_running()\n
    Source code in fluid/utils/worker.py
    def is_running(self) -> bool:\n    return self._running\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.is_stopping","title":"is_stopping","text":"
    is_stopping()\n
    Source code in fluid/utils/worker.py
    def is_stopping(self) -> bool:\n    return self._workers.is_stopping()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.start_running","title":"start_running","text":"
    start_running()\n
    Source code in fluid/utils/worker.py
    @contextmanager\ndef start_running(self) -> Generator:\n    if self._running:\n        raise RuntimeError(\"Worker is already running\")\n    self._running = True\n    try:\n        logger.info(\"%s started running\", self.worker_name)\n        yield\n    finally:\n        self._running = False\n        logger.warning(\"%s stopped running\", self.worker_name)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.create_task","title":"create_task","text":"
    create_task(worker)\n
    Source code in fluid/utils/worker.py
    def create_task(self, worker: Worker) -> asyncio.Task:\n    return asyncio.create_task(\n        self._run_worker(worker), name=f\"{self.worker_name}-{worker.worker_name}\"\n    )\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.on_shutdown","title":"on_shutdown async","text":"
    on_shutdown()\n

    called after the workers are stopped

    Source code in fluid/utils/worker.py
    async def on_shutdown(self) -> None:\n    \"\"\"called after the workers are stopped\"\"\"\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.shutdown","title":"shutdown async","text":"
    shutdown()\n

    shutdown the workers

    Source code in fluid/utils/worker.py
    async def shutdown(self) -> None:\n    \"\"\"shutdown the workers\"\"\"\n    if self._has_shutdown:\n        return\n    self._has_shutdown = True\n    logger.warning(\n        \"gracefully stopping %d workers: %s\",\n        self.num_workers,\n        \", \".join(w.worker_name for w in self._workers.workers),\n    )\n    self.gracefully_stop()\n    try:\n        async with asyncio.timeout(self._stopping_grace_period):\n            await self.wait_for_exit()\n        await self.on_shutdown()\n        return\n    except asyncio.TimeoutError:\n        logger.warning(\n            \"could not stop workers %s gracefully after %s\"\n            \" seconds - force shutdown\",\n            \", \".join(\n                task.get_name() for task in self._workers.tasks if not task.done()\n            ),\n            self._stopping_grace_period,\n        )\n    except asyncio.CancelledError:\n        pass\n    self._force_shutdown = True\n    self._workers.cancel()\n    try:\n        await self.wait_for_exit()\n    except asyncio.CancelledError:\n        pass\n    await self.on_shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.bail_out","title":"bail_out","text":"
    bail_out(reason, code=1)\n
    Source code in fluid/utils/worker.py
    def bail_out(self, reason: str, code: int = 1) -> None:\n    self.gracefully_stop()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.safe_run","title":"safe_run async","text":"
    safe_run()\n

    Context manager to run a worker safely

    Source code in fluid/utils/worker.py
    @asynccontextmanager\nasync def safe_run(self) -> AsyncGenerator:\n    \"\"\"Context manager to run a worker safely\"\"\"\n    try:\n        yield\n    except asyncio.CancelledError:\n        if self._force_shutdown:\n            # we are shutting down, this is expected\n            pass\n        raise\n    except Exception as e:\n        reason = f\"unhandled exception while running workers: {e}\"\n        logger.exception(reason)\n        asyncio.get_event_loop().call_soon(self.bail_out, reason, 2)\n    else:\n        # worker finished without error\n        # make sure we are shutting down\n        asyncio.get_event_loop().call_soon(self.bail_out, \"worker exit\", 1)\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.add_workers","title":"add_workers","text":"
    add_workers(*workers)\n

    add workers to the workers

    They can be added while the workers are running.

    Source code in fluid/utils/worker.py
    def add_workers(self, *workers: Worker) -> None:\n    \"\"\"add workers to the workers\n\n    They can be added while the workers are running.\n    \"\"\"\n    workers_, tasks_ = self._workers.workers_tasks()\n    for worker in workers:\n        workers_.append(worker)\n        tasks_.append(self.create_task(worker))\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.run","title":"run async","text":"
    run()\n
    Source code in fluid/utils/worker.py
    async def run(self) -> None:\n    with self.start_running():\n        while not self.is_stopping():\n            for worker, task in zip(self._workers.workers, self._workers.tasks):\n                if worker.is_stopping() or task.done():\n                    break\n            await asyncio.sleep(self._heartbeat)\n        await self.shutdown()\n
    "},{"location":"reference/workers/#fluid.utils.worker.DynamicWorkers.wait_for_exit","title":"wait_for_exit async","text":"
    wait_for_exit()\n
    Source code in fluid/utils/worker.py
    async def wait_for_exit(self) -> None:\n    await asyncio.gather(*self._workers.tasks)\n
    "},{"location":"tutorials/","title":"Tutorials","text":"

    The step-by-step guides, the how-to's, the recipes, and all the Aio Fluid parts you can use in your applications.

    "},{"location":"tutorials/db/","title":"Async Database","text":"

    The fluid.db module provides a simple asynchronous interface to interact with postgres databases. It is built on top of the sqlalchemy and asyncpg libraries.

    "},{"location":"tutorials/dispatchers/","title":"Event Dispatchers","text":"

    Event dispatchers are a way to decouple the event source from the event handler. This is useful when you want to have multiple handlers for the same event, or when you want to have a single handler for multiple events.

    from fluid.utils.dispatcher import SimpleDispatcher\n\nsimple = SimpleDispatcher[Any]()\n\nsimple.dispatch(\"you can dispatch anything to this generic dispatcher\")\n
    "},{"location":"tutorials/scheduler/","title":"Task Queue","text":"

    This module has a lightweight implementation of a distributed task producer (TaskScheduler) and consumer (TaskConsumer). The middleware for distributing tasks can be configured via the Broker interface. A redis broker is provided for convenience.

    "},{"location":"tutorials/scheduler/#tasks","title":"Tasks","text":"

    Tasks are standard python async functions decorated with the task decorator.

    from fluid.scheduler import task, TaskRun\n\n@task\nasync def say_hi(ctx: TaskRun):\n    return \"Hi!\"\n

    There are two types of tasks implemented

    • Simple concurrent tasks - they run concurrently with the task consumer - thy must be IO type tasks (no heavy CPU bound operations)
      from fluid.scheduler import task, TaskRun\n\n  @task\n  async def fecth_data(ctx: TaskRun):\n      # fetch data\n      data = await http_cli.get(\"https://...\")\n      data_id = await datastore_cli.stote(data)\n      # trigger another task\n      ctx.task_manager.queue(\"heavy_calculation\", data_id=data_id)\n
    • CPU bound tasks - they run on a subprocess
    from fluid.scheduler import task, TaskRun\n\n@task(cpu_bound=True)\nasync def heavy_calculation(ctx: TaskRun):\n    data = await datastore_cli.get(ctx.params[\"data_id\"])\n    # perform some heavy calculation\n    ...\n    # trigger another task\n    ctx.task_manager.queue(\"fetch_data\")\n

    Both tasks can be periodically scheduled via the schedule keyword argument:

    from datetime import timedelta\nfrom fluid.scheduler import task, TaskContext, every\n\n@task(schedule=every(timedelta(seconds=1)))\nasync def scheduled(context: TaskContext) -> str:\n    await asyncio.sleep(0.1)\n    return \"OK\"\n
    "},{"location":"tutorials/scheduler/#broker","title":"Broker","text":"

    A Task broker needs to implement three abstract methods

      @abstractmethod\n  async def queue_task(self, queued_task: QueuedTask) -> TaskRun:\n      \"\"\"Queue a task\"\"\"\n\n  @abstractmethod\n  async def get_task_run(self) -> Optional[TaskRun]:\n      \"\"\"Get a Task run from the task queue\"\"\"\n\n  @abstractmethod\n  async def queue_length(self) -> Dict[str, int]:\n      \"\"\"Length of task queues\"\"\"\n

    The library ships a Redis broker for convenience.

    from fluid.scheduler import Broker\n\nredis_broker = Broker.from_url(\"redis://localhost:6349\")\n
    "}]} \ No newline at end of file