Attributes#
| Attribute | Type | Description |
|---|---|---|
capacity | int | None | How many unread messages the hub holds; |
Functions#
__init__#
__init__(atomic, strategy) -> None| Parameter | Type | Description |
|---|---|---|
atomic | Atomic[A] | |
strategy | Strategy |
def __init__(self, atomic: Atomic[A], strategy: Strategy) -> None:
self._hub = Hub(atomic, strategy)make#
make(atomic, strategy) -> Effect[PubSub[T]]A hub over the store atomic() builds, handling a full store by
strategy (Effect's make, with the built-in strategies).
| Parameter | Type | Description |
|---|---|---|
atomic | Callable[[], Atomic[T]] | |
strategy | Strategy |
Returns Effect[PubSub[T]]
@staticmethod
def make[T](atomic: Callable[[], Atomic[T]], strategy: Strategy) -> Effect[PubSub[T]]:
"""A hub over the store ``atomic()`` builds, handling a full store by
``strategy`` (Effect's ``make``, with the built-in strategies)."""
return _Sync(lambda: PubSub(atomic(), strategy))bounded#
bounded(capacity, *, replay=None) -> Effect[PubSub[A]]Publishers wait while capacity messages are unread. replay
messages are kept for new subscribers. A capacity below 1 is a
defect; None is unbounded.
| Parameter | Type | Description |
|---|---|---|
capacity | int | None | |
replay | int | None = None |
Returns Effect[PubSub[A]]
@classmethod
def bounded(cls, capacity: int | None, *, replay: int | None = None) -> Effect[PubSub[A]]:
"""Publishers wait while ``capacity`` messages are unread. ``replay``
messages are kept for new subscribers. A capacity below 1 is a
defect; ``None`` is unbounded."""
return _Sync(lambda: cls(Atomic(capacity, replay), "suspend"))dropping#
dropping(capacity, *, replay=None) -> Effect[PubSub[A]]A publish to a full hub drops the message and returns False.
| Parameter | Type | Description |
|---|---|---|
capacity | int | None | |
replay | int | None = None |
Returns Effect[PubSub[A]]
@classmethod
def dropping(cls, capacity: int | None, *, replay: int | None = None) -> Effect[PubSub[A]]:
"""A publish to a full hub drops the message and returns ``False``."""
return _Sync(lambda: cls(Atomic(capacity, replay), "dropping"))sliding#
sliding(capacity, *, replay=None) -> Effect[PubSub[A]]A publish to a full hub drops the oldest unread message.
| Parameter | Type | Description |
|---|---|---|
capacity | int | None | |
replay | int | None = None |
Returns Effect[PubSub[A]]
@classmethod
def sliding(cls, capacity: int | None, *, replay: int | None = None) -> Effect[PubSub[A]]:
"""A publish to a full hub drops the oldest unread message."""
return _Sync(lambda: cls(Atomic(capacity, replay), "sliding"))unbounded#
unbounded(*, replay=None) -> Effect[PubSub[A]]| Parameter | Type | Description |
|---|---|---|
replay | int | None = None |
Returns Effect[PubSub[A]]
@classmethod
def unbounded(cls, *, replay: int | None = None) -> Effect[PubSub[A]]:
return _Sync(lambda: cls(Atomic(None, replay), "dropping"))publish#
publish(value) -> Effect[bool]Publish to every current subscriber. False if the hub ended or
shut down, or a dropping hub is full; a bounded hub waits for room.
| Parameter | Type | Description |
|---|---|---|
value | A |
Returns Effect[bool]
def publish(self, value: A) -> Effect[bool]:
"""Publish to every current subscriber. ``False`` if the hub ended or
shut down, or a dropping hub is full; a bounded hub waits for room."""
def register(resume: Callable[[Effect[bool]], None]) -> Effect[None] | None:
hub = self._hub
if self.unsafe_publish(value):
resume(_Succeed(True))
elif not hub.accepts() or hub.strategy == "dropping":
resume(_Succeed(False))
elif hub.strategy == "sliding":
resume(_Succeed(self._slide_in([value])))
else:
return self._park([value], resume)
return None
return _Callback(register)unsafe_publish#
unsafe_publish(value) -> boolPublish without waiting, sliding or dropping: False if the
store is full. Call on the scheduler thread of the hub's fibers.
| Parameter | Type | Description |
|---|---|---|
value | A |
Returns bool
def unsafe_publish(self, value: A) -> bool:
"""Publish without waiting, sliding or dropping: ``False`` if the
store is full. Call on the scheduler thread of the hub's fibers."""
hub = self._hub
if not hub.accepts() or not hub.atomic.publish(value):
return False
hub.deliver()
return Truepublish_all#
publish_all(items) -> Effect[bool]Publish items in order; True if every one was published.
A bounded hub publishes what fits and waits to publish the rest.
| Parameter | Type | Description |
|---|---|---|
items | Iterable[A] |
Returns Effect[bool]
def publish_all(self, items: Iterable[A]) -> Effect[bool]:
"""Publish ``items`` in order; ``True`` if every one was published.
A bounded hub publishes what fits and waits to publish the rest."""
def register(resume: Callable[[Effect[bool]], None]) -> Effect[None] | None:
hub = self._hub
if not hub.accepts():
resume(_Succeed(False))
return None
surplus = hub.atomic.publish_all(items)
hub.deliver()
if not surplus:
resume(_Succeed(True))
elif hub.strategy == "dropping":
resume(_Succeed(False))
elif hub.strategy == "sliding":
resume(_Succeed(self._slide_in(surplus)))
else:
return self._park(surplus, resume)
return None
return _Callback(register)end#
end(value) -> Effect[bool]Publish nothing more. Subscribers take what they have not read,
then value from every take; waiting publishes return False.
False if the hub already ended or shut down.
| Parameter | Type | Description |
|---|---|---|
value | A |
Returns Effect[bool]
def end(self, value: A) -> Effect[bool]:
"""Publish nothing more. Subscribers take what they have not read,
then ``value`` from every take; waiting publishes return ``False``.
``False`` if the hub already ended or shut down."""
return _Sync(lambda: self.unsafe_end(value))unsafe_end#
unsafe_end(value) -> bool| Parameter | Type | Description |
|---|---|---|
value | A |
Returns bool
def unsafe_end(self, value: A) -> bool:
hub = self._hub
if not hub.accepts():
return False
hub.ended = Some(value)
hub.reject_publishers()
hub.wake_takers()
return Truesubscribe#
subscribe() -> Effect[Subscription[A], Never, Scope]Subscribe until the current scope closes (or the hub shuts down). The subscription reads the replayed messages, then everything published from now on.
Returns Effect[Subscription[A], Never, Scope]
def subscribe(self) -> Effect[Subscription[A], Never, Scope]:
"""Subscribe until the current scope closes (or the hub shuts down).
The subscription reads the replayed messages, then everything
published from now on."""
hub = self._hub
def body():
local = yield from Scope()
scope = yield from hub.scope.fork()
reader = hub.subscribe()
yield from scope.add_finalizer(
lambda _: _WithFiber(lambda fiber: _Sync(lambda: hub.unsubscribe(reader, fiber.id)))
)
yield from local.add_finalizer(scope.close)
return Subscription[A](hub, reader)
return _Gen(body).uninterruptible()shutdown#
shutdown() -> Effect[None]Unsubscribe everyone, interrupting their takes. Later publishes
return False. Waiting publishes complete: with nobody subscribed
the store empties and admits them (as in Effect, whose strategy
shutdown then finds no publisher left to interrupt).
Returns Effect[None]
def shutdown(self) -> Effect[None]:
"""Unsubscribe everyone, interrupting their takes. Later publishes
return ``False``. Waiting publishes complete: with nobody subscribed
the store empties and admits them (as in Effect, whose strategy
shutdown then finds no publisher left to interrupt)."""
def body(fiber: Fiber[Any, Any]) -> Effect[None]:
hub = self._hub
if hub.is_shutdown:
return _Succeed(None)
hub.is_shutdown = True
hub.shutdown_waiters.notify_all()
return hub.scope.close(Failure(interrupt_cause(fiber.id)))
return _WithFiber(body).uninterruptible()is_shutdown#
is_shutdown() -> Effect[bool]Returns Effect[bool]
def is_shutdown(self) -> Effect[bool]:
return _Sync(self.unsafe_is_shutdown)unsafe_is_shutdown#
unsafe_is_shutdown() -> boolReturns bool
def unsafe_is_shutdown(self) -> bool:
return self._hub.is_shutdownawait_shutdown#
await_shutdown() -> Effect[None]Wait until the hub is shut down.
Returns Effect[None]
def await_shutdown(self) -> Effect[None]:
"""Wait until the hub is shut down."""
return _Suspend(lambda: self._hub.shutdown_waiters.wait(self.unsafe_is_shutdown))size#
size() -> Effect[int]How many messages are stored unread (0 once shut down).
Returns Effect[int]
def size(self) -> Effect[int]:
"""How many messages are stored unread (0 once shut down)."""
return _Sync(self.unsafe_size)unsafe_size#
unsafe_size() -> intReturns int
def unsafe_size(self) -> int:
return 0 if self._hub.is_shutdown else self._hub.atomic.size()is_full#
is_full() -> Effect[bool]Returns Effect[bool]
def is_full(self) -> Effect[bool]:
return _Sync(lambda: self.unsafe_size() == self.capacity)is_empty#
is_empty() -> Effect[bool]Returns Effect[bool]
def is_empty(self) -> Effect[bool]:
return _Sync(lambda: self.unsafe_size() == 0)