Observed since 20 Oct, 20:09 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
aedb
Python SDK for event-driven services: NATS daemons, contracts, storage, and infrastructure clients
aedb — Python SDK для демонов платформы. Публичный интерфейс
позволяет подключить демон к NATS, принимать события и задачи, отвечать на RPC
и обрабатывать длительные задачи JetStream.
Требуется Python 3.14.
python -m pip install aedb
export DAEMON_NATS_HOST='nats://localhost:4222'
export DAEMON_NATS_SEED='SU...'
DAEMON_NATS_HOST — адрес NATS; DAEMON_NATS_SEED — секретный NKey seed
демона. Оба значения обязательны. Не записывайте seed в исходный код.
Таймауты подключения и переподключения можно задать через
DAEMON_NATS_TIMEOUT и DAEMON_NATS_RECONNECT_TIMEOUT (по умолчанию 3 секунды).
DaemonSettings() читает эти переменные при создании объекта. При необходимости
можно передать NATSSettings(host=..., seed=...) явно.
Для первой активации демона укажите также DAEMON_JOIN_HOST — базовый URL
Join-сервиса — и вызовите await daemon.join(token) с одноразовым токеном
до запуска соединения. Join не вызывается автоматически; при следующих
запусках уже активированного демона токен не нужен.
import asyncio
from aedb.contracts import Event
from aedb.engine.daemons import Daemon, DaemonSettings
daemon = Daemon(DaemonSettings())
@daemon.listen.events("demo.events")
async def on_event(event: Event) -> None:
print(event.payload)
@daemon.listen.rpc("demo.echo")
async def echo(event: Event) -> Event:
return Event(task_id=event.task_id, payload=event.payload)
async def main() -> None:
async with daemon:
await daemon.action.event("demo.events", {"text": "hello"})
answer = await daemon.action.rpc("demo.echo", {"text": "ping"})
print(answer.payload)
asyncio.run(main())
async with daemon: открывает NATS-соединение и подписки, а при выходе
закрывает их. Если управление жизненным циклом нужно вручную, используйте
await daemon.start() и await daemon.close(). Обработчики можно
зарегистрировать до подключения. Для обмена сообщениями нужны права NATS
на соответствующие subjects.
Event — JSON-конверт с id, необязательным task_id, meta, timestamp
и словарём payload. Методы daemon.action.event, task и rpc принимают
как Event, так и словарь payload. rpc возвращает Event.
| Приём | Отправка | Назначение |
|---|---|---|
@daemon.listen.events(subject) | await daemon.action.event(subject, payload) | Событие без ответа. |
@daemon.listen.task(subject, group=None) | await daemon.action.task(subject, reply, payload) | Задача с явным reply-subject; ответ обработчика публикуется туда, если он есть. group задаёт NATS queue group. |
@daemon.listen.rpc(subject) | await daemon.action.rpc(subject, payload, timeout=None) | Запрос с ожиданием ответа Event. |
Обработчик получает Event и может быть синхронной или асинхронной функцией.
Для task и rpc результат отправляется только при наличии reply-subject
и ненулевого результата. Для action.task ответ следует принимать отдельным
обработчиком listen.events(reply).
@daemon.listen.long_task(...) принимает сообщения из заранее созданного
durable consumer с explicit ack и фильтром по subject. Асинхронный
обработчик возвращает Event с тем же task_id, что у запроса, либо словарь
payload. SDK публикует ответ в reply_to и подтверждает входящее сообщение
после успешной публикации. При ошибке запрашивается повторная доставка.
from aedb.contracts import Event
@daemon.listen.long_task(
"demo.jobs.request",
stream="DEMO_JOBS",
consumer="worker",
reply_to="demo.jobs.answer",
progress_every=20.0,
retry_delay=5.0,
)
async def process(event: Event) -> Event:
return Event(task_id=event.task_id, payload={"result": event.payload})
# Выполнять после запуска демона:
# ack = await daemon.action.long_task(
# "demo.jobs.request", Event(task_id="job-1", payload={"value": 42})
# )
progress_every должен быть меньше AckWait consumer. action.long_task
возвращает подтверждение публикации JetStream, но не ждёт результата задачи.
Результат поступает отдельно на reply_to.
aedb engine keyКоманда создаёт NKey-пару или выводит публичный ключ из существующего seed:
aedb engine key
aedb engine key --type account
aedb engine key --save ./worker
aedb engine key --seed "$(cat ./worker.seed)"
aedb engine key --seed "$(cat ./worker.seed)" --save ./worker-public
По умолчанию создаётся пара типа user. --type принимает user, account,
server, operator или cluster. --save BASE сохраняет seed и публичный
ключ в BASE.seed и BASE.pub с правами 0600. При --seed SEED новая пара
не создаётся: выводится только публичный ключ, а с --save сохраняется только
файл BASE.pub.
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
email-validatorEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | email-validator==2.3.0 | runtime |
jsonschemaEnvironment{
"extras": "format-nongpl",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | jsonschema[format-nongpl]==4.25.1 | runtime |
kubernetesEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | kubernetes==36.0.3 | runtime |
nats-coreEnvironment{
"extras": "nkeys",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | nats-core[nkeys]==0.2.0 | runtime |
nats-jetstreamEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | nats-jetstream==0.3.0 | runtime |
pydantic-settingsEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | pydantic-settings==2.15.0 | runtime |
pydanticEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | pydantic==2.13.5 | runtime |
pynaclEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | pynacl==1.6.2 | runtime |
redisEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | redis==8.1.0 | runtime |
resendEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | resend==2.47.0 | runtime |
surrealdbEnvironment{
"extras": "pydantic",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | surrealdb[pydantic]==2.0.0 | runtime |
typerEnvironment{
"extras": "",
"marker": null,
"requires_python": "==3.14.*",
"evaluation": "NOT_EVALUATED"
} | typer==0.27.2 | runtime |
bdist_wheel · 89.43 KB · Python py3
sdist · 94.53 KB · Python source
Observed since 20 Oct, 20:09 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:64d3cfe9b0be9daf7afe9282ef9b40e17e55841655cfa080a376fbd871e8ec85