py-scopes/scopes/core/actor.py

40 lines
1 KiB
Python

# scopes.core.actor
import asyncio
from collections.abc import Awaitable, Callable
from typing import Any, Optional
from scopes.util import keywords as k, Symbol
# keywords:
k('active full ok quit retired suspended')
type Behavior = Callable[[Any], Awaitable[Behavior | None]]
class Mailbox:
def __init__(self, maxsize:int = 0, status: Symbol = k.active):
self.queue: asyncio.Queue = asyncio.Queue(maxsize)
self.status: Symbol = status
async def loop(q: asyncio.Queue, bhv: Behavior) -> None:
while True:
msg = await q.get()
if msg is k.quit:
break
bhv = await bhv(msg) or bhv
q.task_done()
def create(bhv: Behavior, maxsize: int = 0) -> Mailbox:
mb = Mailbox(maxsize)
asyncio.create_task(loop(mb.queue, bhv))
return mb
async def send(mb: Mailbox, msg: Any, no_wait: bool = False) -> Symbol:
if mb.status is k.retired:
return k.retired
if no_wait and mb.queue.full():
return k.full
await mb.queue.put(msg)
return k.ok