generated from coulomb/repo-seed
Add event-payload context resolver
This commit is contained in:
@@ -11,6 +11,7 @@ activities that need DB access.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
@@ -65,6 +66,24 @@ def _bind_resolver_result(bind_key: str, result: Any) -> Any:
|
||||
return result
|
||||
|
||||
|
||||
def _parse_event_envelope(event_envelope_json: str | None) -> dict[str, Any] | None:
|
||||
"""Parse an event envelope JSON string for context resolvers."""
|
||||
if not event_envelope_json:
|
||||
return None
|
||||
try:
|
||||
payload = json.loads(event_envelope_json)
|
||||
except (TypeError, json.JSONDecodeError) as exc:
|
||||
activity.logger.warning("Invalid event envelope JSON - %s", exc)
|
||||
return None
|
||||
if not isinstance(payload, dict):
|
||||
activity.logger.warning(
|
||||
"Invalid event envelope JSON - expected object, got %s",
|
||||
type(payload).__name__,
|
||||
)
|
||||
return None
|
||||
return payload
|
||||
|
||||
|
||||
# ── Activities ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@activity.defn
|
||||
@@ -124,6 +143,7 @@ async def resolve_context(
|
||||
from activity_core.context_resolvers.base import CONTEXT_RESOLVER_REGISTRY
|
||||
|
||||
snapshot: dict = {}
|
||||
event_envelope = _parse_event_envelope(event_envelope_json)
|
||||
for source in context_sources:
|
||||
source_type = source.get("type", "")
|
||||
query = source.get("query", "")
|
||||
@@ -152,7 +172,7 @@ async def resolve_context(
|
||||
continue
|
||||
|
||||
try:
|
||||
resolved = resolver_cls().resolve(query, None, params)
|
||||
resolved = resolver_cls().resolve(query, event_envelope, params)
|
||||
snapshot[bind_key] = _bind_resolver_result(bind_key, resolved)
|
||||
except Exception as exc:
|
||||
if required:
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
from activity_core.context_resolvers import kaizen, ops_inventory, repo_scoping, state_hub # noqa: F401
|
||||
from activity_core.context_resolvers import ( # noqa: F401
|
||||
event_payload,
|
||||
kaizen,
|
||||
ops_inventory,
|
||||
repo_scoping,
|
||||
state_hub,
|
||||
)
|
||||
|
||||
51
src/activity_core/context_resolvers/event_payload.py
Normal file
51
src/activity_core/context_resolvers/event_payload.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""Event payload context adapter.
|
||||
|
||||
Registered as source type ``event-payload``. It exposes the triggering
|
||||
EventEnvelope attributes to event-triggered ActivityDefinitions without
|
||||
requiring an external context service call.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from activity_core.context_resolvers.base import CONTEXT_RESOLVER_REGISTRY, ContextResolver
|
||||
|
||||
|
||||
class EventPayloadContextResolver(ContextResolver):
|
||||
"""Resolve context from the triggering event envelope attributes."""
|
||||
|
||||
def resolve(self, query: str, event: Any, params: dict[str, Any]) -> Any:
|
||||
attributes = _event_attributes(event)
|
||||
if query in {"", "attributes"}:
|
||||
return attributes
|
||||
if query.startswith("attributes."):
|
||||
return _resolve_path(attributes, query.removeprefix("attributes."))
|
||||
return _resolve_path(attributes, query)
|
||||
|
||||
|
||||
def _event_attributes(event: Any) -> dict[str, Any]:
|
||||
if not isinstance(event, dict):
|
||||
raise RuntimeError("event-payload source requires an event envelope")
|
||||
attributes = event.get("attributes")
|
||||
if not isinstance(attributes, dict):
|
||||
raise RuntimeError("event-payload source requires envelope attributes")
|
||||
return attributes
|
||||
|
||||
|
||||
def _resolve_path(root: dict[str, Any], path: str) -> Any:
|
||||
if not path:
|
||||
return root
|
||||
current: Any = root
|
||||
for part in path.split("."):
|
||||
if not part:
|
||||
return {}
|
||||
if not isinstance(current, dict):
|
||||
return {}
|
||||
current = current.get(part)
|
||||
if current is None:
|
||||
return {}
|
||||
return current
|
||||
|
||||
|
||||
CONTEXT_RESOLVER_REGISTRY["event-payload"] = EventPayloadContextResolver
|
||||
Reference in New Issue
Block a user