From c4ca2fdce08534ce5bb4d5e8cfd4b3ce5b109333 Mon Sep 17 00:00:00 2001 From: Mohammad Dashti Date: Sat, 3 Oct 2026 01:57:02 -0700 Subject: [PATCH 1/2] Added a streams demo that runs the agent loop on a provider. One agent loop, read, decide, publish and an activity, that runs unchanged on every provider, so a provider branch only swaps provider_setup. --- pyproject.toml | 2 +- streams_demo/agent_loop.py | 110 ++++ streams_demo/provider_setup.py | 36 ++ streams_demo/results-memory/history.json | 660 +++++++++++++++++++++++ streams_demo/results-memory/results.json | 115 ++++ streams_demo/run_demo.py | 174 ++++++ 6 files changed, 1096 insertions(+), 1 deletion(-) create mode 100644 streams_demo/agent_loop.py create mode 100644 streams_demo/provider_setup.py create mode 100644 streams_demo/results-memory/history.json create mode 100644 streams_demo/results-memory/results.json create mode 100644 streams_demo/run_demo.py diff --git a/pyproject.toml b/pyproject.toml index a83b34cd7..cacec1ad0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -267,7 +267,7 @@ reportUnnecessaryIsInstance = "none" reportUnnecessaryTypeIgnoreComment = "none" reportUnusedCallResult = "none" reportUnknownLambdaType = "none" -include = ["temporalio", "tests"] +include = ["temporalio", "tests", "streams_demo"] exclude = [ # Exclude auto generated files "temporalio/api", diff --git a/streams_demo/agent_loop.py b/streams_demo/agent_loop.py new file mode 100644 index 000000000..df5eac4d6 --- /dev/null +++ b/streams_demo/agent_loop.py @@ -0,0 +1,110 @@ +"""One agent loop, written once, run on every stream provider. + +Reads input, decides on it, publishes the decision, and runs an ordinary +Activity in the same workflow task; the Activity reports on its own +workflow's stream in turn. Also handles the two control records the contract +defines, so a retried producer and a finished topic are exercised rather than +described. + +This file is byte-identical in the server-side tree and the client-side tree. +Nothing in it names a provider: the workflow asks its runtime, the Activity +asks its context, and the process that runs them registered the provider once. +""" + +from __future__ import annotations + +from datetime import timedelta +from typing import Any + +from temporalio import activity, streams, workflow +from temporalio.streams import RecordKind + +# Defined once and shared by the workflow, the Activity and the demo's +# reader, so the type each topic carries is stated in one place. +DECISIONS = streams.topic("decisions", dict[str, Any]) +INPUTS = streams.topic("inputs", dict[str, Any]) +RECEIPTS = streams.topic("receipts", dict[str, Any]) + + +@activity.defn(name="RecordDecision") +async def record_decision(decision: dict[str, Any]) -> str: + """An ordinary command in the same task as the publish. + + Appends its receipt onto its own workflow's stream too, under the + Activity's own identity, so a reader outside sees the decision and the + record of it side by side. + """ + receipt = f"recorded:{decision['source']}:{decision['branch']}" + await activity.stream_handle().producer(topic=RECEIPTS).append({"receipt": receipt}) + return receipt + + +def decide(token: dict[str, Any]) -> dict[str, Any]: + """The decision the workflow is here to make.""" + if token["value"] % 2 == 0: + return { + "source": token["id"], + "branch": "even", + "computed": token["value"] * 10, + } + return {"source": token["id"], "branch": "odd", "computed": token["value"] + 100} + + +@workflow.defn(name="StreamContractDemo", sandboxed=False) +class AgentLoop: + """Read, decide, write, until the producer says it has finished.""" + + @workflow.run + async def run(self, limit: int) -> list[dict[str, Any]]: + """Decide on at most ``limit`` inputs, then return the trace.""" + inputs = workflow.stream_reader(INPUTS) + decisions = workflow.stream_writer(DECISIONS) + trace: list[dict[str, Any]] = [] + accepted = 0 + try: + async for record in inputs: + if record.kind is RecordKind.SUPERSEDED: + # A newer attempt of the same producer started writing. The + # decisions already published stand, so the workflow says so + # rather than pretending they can be withdrawn. + assert record.supersession is not None + trace.append( + { + "kind": "superseded", + "producer": record.producer_id, + "replaced": record.supersession.previous_attempt, + "attempt": record.supersession.attempt, + } + ) + decisions.publish( + {"retracting_attempt": record.supersession.previous_attempt} + ) + continue + if record.kind is RecordKind.FINISH: + # The producer says it is done, which is what ends the loop. + # Counting decisions instead would leave the terminal record + # unread and let the workflow finish while its producer is + # still writing. + trace.append({"kind": "finish", "producer": record.producer_id}) + break + assert record.value is not None + decision = decide(record.value) + decisions.publish(decision) + receipt = await workflow.execute_activity( + record_decision, + decision, + activity_id=f"decision-{decision['source']}", + start_to_close_timeout=timedelta(seconds=10), + ) + trace.append( + {"kind": "decision", "value": decision, "receipt": receipt} + ) + accepted += 1 + if accepted >= limit: + # A bound so a stuck producer cannot run this forever. The + # terminal record above is the ordinary way out. + break + finally: + inputs.close() + decisions.finish() + return trace diff --git a/streams_demo/provider_setup.py b/streams_demo/provider_setup.py new file mode 100644 index 000000000..2e4bcc350 --- /dev/null +++ b/streams_demo/provider_setup.py @@ -0,0 +1,36 @@ +"""Pick the provider for a demo run from the environment. + +``STREAMS_PROVIDER`` names a provider; this base tree carries only ``memory``, +and each provider branch adds its own name here. The demo needs a Temporal +server to run the workflow either way; ``TEMPORAL_ADDRESS`` points at it. +""" + +from __future__ import annotations + +import os + +from temporalio.streams.providers import ProviderPlugin +from temporalio.streams.providers.memory import MemoryStreams + +NAME = os.environ.get("STREAMS_PROVIDER", "memory") + +# The memory provider is not replay-safe, so its demo keeps the cache warm. +# Storage providers run with the smallest cache they support instead. +WORKFLOW_CACHE = int(os.environ.get("STREAMS_WORKFLOW_CACHE", "512")) + + +async def open() -> tuple[str, ProviderPlugin]: + """The server to connect to and the provider the worker and the client share.""" + if NAME != "memory": + raise SystemExit(f"this tree carries no stream provider named {NAME!r}") + return os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), MemoryStreams() + + +async def close(provider: ProviderPlugin) -> None: + """Let go of whatever :func:`open` acquired. + + The memory provider holds no connection, so this is its ``close()`` and + nothing more. A provider branch that opens one closes it the same way, so + the demo's teardown reads the same on every provider. + """ + await provider.close() diff --git a/streams_demo/results-memory/history.json b/streams_demo/results-memory/history.json new file mode 100644 index 000000000..b98211075 --- /dev/null +++ b/streams_demo/results-memory/history.json @@ -0,0 +1,660 @@ +{ + "events": [ + { + "eventId": "1", + "eventTime": "2026-10-03T08:56:51.314386Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED", + "taskId": "2105644", + "workflowExecutionStartedEventAttributes": { + "workflowType": { + "name": "StreamContractDemo" + }, + "taskQueue": { + "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "OA==" + } + ] + }, + "workflowTaskTimeout": "10s", + "originalExecutionRunId": "01a100fa-fd72-75a9-8676-068fe15f9419", + "identity": "13139@Moes-MacBook-Pro.local", + "firstExecutionRunId": "01a100fa-fd72-75a9-8676-068fe15f9419", + "attempt": 1, + "firstWorkflowTaskBackoff": "0s", + "workflowId": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "priority": {} + } + }, + { + "eventId": "2", + "eventTime": "2026-10-03T08:56:51.326362Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "2105645", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "3", + "eventTime": "2026-10-03T08:56:51.372051Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "2105650", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "2", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "425e75d3-cde6-4fd5-a9e7-7bd4270d26fe", + "historySizeBytes": "412", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "4", + "eventTime": "2026-10-03T08:56:51.442115Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "2105655", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "2", + "startedEventId": "3", + "identity": "13139@Moes-MacBook-Pro.local", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + }, + "sdkMetadata": { + "coreUsedFlags": [ + 3, + 1, + 2 + ], + "sdkName": "temporal-python", + "sdkVersion": "1.33.0" + }, + "meteringMetadata": {} + } + }, + { + "eventId": "5", + "eventTime": "2026-10-03T08:56:51.443333Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "2105656", + "activityTaskScheduledEventAttributes": { + "activityId": "decision-r1", + "activityType": { + "name": "RecordDecision" + }, + "taskQueue": { + "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJicmFuY2giOiJvZGQiLCJjb21wdXRlZCI6MTAxLCJzb3VyY2UiOiJyMSJ9" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "10s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "4", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + } + }, + { + "eventId": "6", + "eventTime": "2026-10-03T08:56:51.443410Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "2105660", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "5", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "e2532e51-340a-460e-b7a4-df6926ef6ad4", + "attempt": 1, + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "7", + "eventTime": "2026-10-03T08:56:51.449160Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "2105661", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InJlY29yZGVkOnIxOm9kZCI=" + } + ] + }, + "scheduledEventId": "5", + "startedEventId": "6", + "identity": "13139@Moes-MacBook-Pro.local" + } + }, + { + "eventId": "8", + "eventTime": "2026-10-03T08:56:51.449369Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "2105662", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "9", + "eventTime": "2026-10-03T08:56:51.473693Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "2105666", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "8", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "c9386a35-2f1b-48f8-9a4a-96dbb5ada323", + "historySizeBytes": "1317", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "10", + "eventTime": "2026-10-03T08:56:51.497035Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "2105671", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "8", + "startedEventId": "9", + "identity": "13139@Moes-MacBook-Pro.local", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "11", + "eventTime": "2026-10-03T08:56:51.497094Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "2105672", + "activityTaskScheduledEventAttributes": { + "activityId": "decision-r2", + "activityType": { + "name": "RecordDecision" + }, + "taskQueue": { + "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJicmFuY2giOiJldmVuIiwiY29tcHV0ZWQiOjIwLCJzb3VyY2UiOiJyMiJ9" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "10s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "10", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + } + }, + { + "eventId": "12", + "eventTime": "2026-10-03T08:56:51.497151Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "2105675", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "11", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "10718666-9e34-4cb8-a29b-5354b02b8478", + "attempt": 1, + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "13", + "eventTime": "2026-10-03T08:56:51.515418Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "2105676", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InJlY29yZGVkOnIyOmV2ZW4i" + } + ] + }, + "scheduledEventId": "11", + "startedEventId": "12", + "identity": "13139@Moes-MacBook-Pro.local" + } + }, + { + "eventId": "14", + "eventTime": "2026-10-03T08:56:51.515466Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "2105677", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "15", + "eventTime": "2026-10-03T08:56:51.517617Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "2105681", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "14", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "6ae9c55e-9311-40e0-9769-252931cba559", + "historySizeBytes": "2192", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "16", + "eventTime": "2026-10-03T08:56:51.521729Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "2105685", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "14", + "startedEventId": "15", + "identity": "13139@Moes-MacBook-Pro.local", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "17", + "eventTime": "2026-10-03T08:56:51.521779Z", + "eventType": "EVENT_TYPE_TIMER_STARTED", + "taskId": "2105686", + "timerStartedEventAttributes": { + "timerId": "1", + "startToFireTimeout": "0.100s", + "workflowTaskCompletedEventId": "16" + } + }, + { + "eventId": "18", + "eventTime": "2026-10-03T08:56:52.518155Z", + "eventType": "EVENT_TYPE_TIMER_FIRED", + "taskId": "2105689", + "timerFiredEventAttributes": { + "timerId": "1", + "startedEventId": "17" + } + }, + { + "eventId": "19", + "eventTime": "2026-10-03T08:56:52.518178Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "2105690", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "20", + "eventTime": "2026-10-03T08:56:52.519801Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "2105694", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "19", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "a50a8cea-96a3-434f-b5a3-13705af68b3f", + "historySizeBytes": "2661", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "21", + "eventTime": "2026-10-03T08:56:52.527177Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "2105699", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "19", + "startedEventId": "20", + "identity": "13139@Moes-MacBook-Pro.local", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "22", + "eventTime": "2026-10-03T08:56:52.527217Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "2105700", + "activityTaskScheduledEventAttributes": { + "activityId": "decision-r3", + "activityType": { + "name": "RecordDecision" + }, + "taskQueue": { + "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJicmFuY2giOiJvZGQiLCJjb21wdXRlZCI6MTAzLCJzb3VyY2UiOiJyMyJ9" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "10s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "21", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + } + }, + { + "eventId": "23", + "eventTime": "2026-10-03T08:56:52.527245Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "2105703", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "22", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "5f5f9ef8-699b-4caf-8272-ad1da4375db9", + "attempt": 1, + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "24", + "eventTime": "2026-10-03T08:56:52.530370Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "2105704", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InJlY29yZGVkOnIzOm9kZCI=" + } + ] + }, + "scheduledEventId": "22", + "startedEventId": "23", + "identity": "13139@Moes-MacBook-Pro.local" + } + }, + { + "eventId": "25", + "eventTime": "2026-10-03T08:56:52.530382Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "2105705", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "26", + "eventTime": "2026-10-03T08:56:52.534111Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "2105709", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "25", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "33492902-eefb-43b1-9134-1ad6fa1bec84", + "historySizeBytes": "3535", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "27", + "eventTime": "2026-10-03T08:56:52.539976Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "2105714", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "25", + "startedEventId": "26", + "identity": "13139@Moes-MacBook-Pro.local", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "28", + "eventTime": "2026-10-03T08:56:52.540016Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "2105715", + "activityTaskScheduledEventAttributes": { + "activityId": "decision-r4", + "activityType": { + "name": "RecordDecision" + }, + "taskQueue": { + "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJicmFuY2giOiJldmVuIiwiY29tcHV0ZWQiOjQwLCJzb3VyY2UiOiJyNCJ9" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "10s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "27", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + } + }, + { + "eventId": "29", + "eventTime": "2026-10-03T08:56:52.540040Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "2105718", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "28", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "10c726d1-3b98-40ea-8cd1-35baaa53c605", + "attempt": 1, + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "30", + "eventTime": "2026-10-03T08:56:52.547729Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "2105719", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InJlY29yZGVkOnI0OmV2ZW4i" + } + ] + }, + "scheduledEventId": "28", + "startedEventId": "29", + "identity": "13139@Moes-MacBook-Pro.local" + } + }, + { + "eventId": "31", + "eventTime": "2026-10-03T08:56:52.547747Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "2105720", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "32", + "eventTime": "2026-10-03T08:56:52.556472Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "2105724", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "31", + "identity": "13139@Moes-MacBook-Pro.local", + "requestId": "2ae24ec7-e165-4ca9-8ead-bbd0523a7bb7", + "historySizeBytes": "4410", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + } + } + }, + { + "eventId": "33", + "eventTime": "2026-10-03T08:56:52.566679Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "2105728", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "31", + "startedEventId": "32", + "identity": "13139@Moes-MacBook-Pro.local", + "workerVersion": { + "buildId": "305b079191a1e625f49047e6956df64a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "34", + "eventTime": "2026-10-03T08:56:52.566723Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED", + "taskId": "2105729", + "workflowExecutionCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "W3sia2luZCI6ImRlY2lzaW9uIiwicmVjZWlwdCI6InJlY29yZGVkOnIxOm9kZCIsInZhbHVlIjp7ImJyYW5jaCI6Im9kZCIsImNvbXB1dGVkIjoxMDEsInNvdXJjZSI6InIxIn19LHsia2luZCI6ImRlY2lzaW9uIiwicmVjZWlwdCI6InJlY29yZGVkOnIyOmV2ZW4iLCJ2YWx1ZSI6eyJicmFuY2giOiJldmVuIiwiY29tcHV0ZWQiOjIwLCJzb3VyY2UiOiJyMiJ9fSx7ImF0dGVtcHQiOjIsImtpbmQiOiJzdXBlcnNlZGVkIiwicHJvZHVjZXIiOiJtb2RlbCIsInJlcGxhY2VkIjoxfSx7ImtpbmQiOiJkZWNpc2lvbiIsInJlY2VpcHQiOiJyZWNvcmRlZDpyMzpvZGQiLCJ2YWx1ZSI6eyJicmFuY2giOiJvZGQiLCJjb21wdXRlZCI6MTAzLCJzb3VyY2UiOiJyMyJ9fSx7ImtpbmQiOiJkZWNpc2lvbiIsInJlY2VpcHQiOiJyZWNvcmRlZDpyNDpldmVuIiwidmFsdWUiOnsiYnJhbmNoIjoiZXZlbiIsImNvbXB1dGVkIjo0MCwic291cmNlIjoicjQifX0seyJraW5kIjoiZmluaXNoIiwicHJvZHVjZXIiOiJtb2RlbCJ9XQ==" + } + ] + }, + "workflowTaskCompletedEventId": "33" + } + } + ] +} \ No newline at end of file diff --git a/streams_demo/results-memory/results.json b/streams_demo/results-memory/results.json new file mode 100644 index 000000000..1efcb3cb8 --- /dev/null +++ b/streams_demo/results-memory/results.json @@ -0,0 +1,115 @@ +{ + "provider": "memory", + "workflow_id": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", + "target": "127.0.0.1:7943", + "max_cached_workflows": 512, + "outcome": "completed", + "trace": [ + { + "kind": "decision", + "receipt": "recorded:r1:odd", + "value": { + "branch": "odd", + "computed": 101, + "source": "r1" + } + }, + { + "kind": "decision", + "receipt": "recorded:r2:even", + "value": { + "branch": "even", + "computed": 20, + "source": "r2" + } + }, + { + "attempt": 2, + "kind": "superseded", + "producer": "model", + "replaced": 1 + }, + { + "kind": "decision", + "receipt": "recorded:r3:odd", + "value": { + "branch": "odd", + "computed": 103, + "source": "r3" + } + }, + { + "kind": "decision", + "receipt": "recorded:r4:even", + "value": { + "branch": "even", + "computed": 40, + "source": "r4" + } + }, + { + "kind": "finish", + "producer": "model" + } + ], + "task_failures": [], + "observed_output": [ + { + "kind": "DATA", + "value": { + "branch": "odd", + "computed": 101, + "source": "r1" + } + }, + { + "kind": "DATA", + "value": { + "branch": "even", + "computed": 20, + "source": "r2" + } + }, + { + "kind": "DATA", + "value": { + "retracting_attempt": 1 + } + }, + { + "kind": "DATA", + "value": { + "branch": "odd", + "computed": 103, + "source": "r3" + } + }, + { + "kind": "DATA", + "value": { + "branch": "even", + "computed": 40, + "source": "r4" + } + }, + { + "kind": "FINISH", + "value": null + } + ], + "receipts": [ + { + "receipt": "recorded:r1:odd" + }, + { + "receipt": "recorded:r2:even" + }, + { + "receipt": "recorded:r3:odd" + }, + { + "receipt": "recorded:r4:even" + } + ], + "history_events": 34 +} diff --git a/streams_demo/run_demo.py b/streams_demo/run_demo.py new file mode 100644 index 000000000..769d7bf18 --- /dev/null +++ b/streams_demo/run_demo.py @@ -0,0 +1,174 @@ +"""Run the shared agent loop against whichever provider is configured. + +Three cases, the same on every provider: + +- read, decide, publish and an ordinary Activity in the same workflow task, + with the smallest workflow cache the provider supports, so that as much of + the run as it allows is rebuilt rather than remembered; +- a producer whose second attempt supersedes its first, which the reader has + to report and the workflow has to act on; +- an outside reader following what the workflow published, and the receipts + the Activity appended on the workflow's stream from inside its own context. + +The provider is registered once, on the client; the worker inherits it and +every context asks for its stream without naming it. Byte-identical in every +tree. ``provider_setup`` is what differs, and it is the only import here that +names a provider. +""" + +from __future__ import annotations + +import asyncio +import json +import sys +import time +import uuid +from pathlib import Path +from typing import Any + +from temporalio.api.enums.v1 import EventType +from temporalio.client import Client +from temporalio.streams import RecordKind, StreamHandle +from temporalio.worker import Worker + +# Run as a script rather than imported as a module, so the two siblings are +# reached by name off this directory rather than through a package path. +sys.path.insert(0, str(Path(__file__).resolve().parent)) +import provider_setup # noqa: E402 # pyright: ignore[reportImplicitRelativeImport] +from agent_loop import ( # noqa: E402 # pyright: ignore[reportImplicitRelativeImport] + DECISIONS, + INPUTS, + RECEIPTS, + AgentLoop, + record_decision, +) + +DECISION_LIMIT = 8 +EXPECTED_OUTPUT = 6 + + +async def collect_output(stream: StreamHandle, want: int) -> list[dict]: + """Read ``want`` decisions off the workflow's stream from outside it.""" + seen: list[dict] = [] + async for record in stream.read(topic=DECISIONS): + seen.append({"kind": record.kind.name, "value": record.value}) + if len(seen) >= want: + break + return seen + + +async def main() -> int: + """Run the demo once and write what happened next to this file.""" + out = Path(__file__).resolve().parent / f"results-{provider_setup.NAME}" + out.mkdir(exist_ok=True) + target, provider = await provider_setup.open() + client = await Client.connect(target, namespace="default", plugins=[provider]) + + uid = f"ai198-contract-{provider_setup.NAME}-" + uuid.uuid4().hex + record: dict[str, Any] = { + "provider": provider_setup.NAME, + "workflow_id": uid, + "target": target, + "max_cached_workflows": provider_setup.WORKFLOW_CACHE, + } + + async with Worker( + client, + task_queue=uid, + workflows=[AgentLoop], + activities=[record_decision], + max_cached_workflows=provider_setup.WORKFLOW_CACHE, + ): + handle = await client.start_workflow( + AgentLoop.run, DECISION_LIMIT, id=uid, task_queue=uid + ) + stream = client.get_stream_handle(uid) + output = asyncio.create_task(collect_output(stream, EXPECTED_OUTPUT)) + + # The first attempt writes two records and then stops, as a failed + # activity would. The second writes different inputs under the same + # logical producer, which is what the reader has to report. + first = stream.producer(topic=INPUTS, producer_id="model", attempt=1) + await first.append({"id": "r1", "value": 1}, {"id": "r2", "value": 2}) + await asyncio.sleep(0.5) + second = stream.producer(topic=INPUTS, producer_id="model", attempt=2) + await second.append({"id": "r3", "value": 3}, {"id": "r4", "value": 4}) + await second.finish() + + # A failed Workflow Task is not an outcome. The server rejects a + # completion that raced newly buffered events, and the retry usually + # gets through, so reading the first failure as the result reports a + # working run as a broken one. Wait for a terminal event, then report + # the retries separately so they are neither the headline nor hidden. + deadline = time.monotonic() + 120 + # Taken from the enum rather than written out, because guessing these + # numbers is how a run that completed gets reported as terminated. + terminal = { + EventType.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED: "completed", + EventType.EVENT_TYPE_WORKFLOW_EXECUTION_FAILED: "workflow_failed", + EventType.EVENT_TYPE_WORKFLOW_EXECUTION_TIMED_OUT: "execution_timed_out", + EventType.EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED: "canceled", + EventType.EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED: "terminated", + EventType.EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW: "continued_as_new", + } + while time.monotonic() < deadline: + history = await handle.fetch_history() + reached = [ + terminal[e.event_type] + for e in history.events + if e.event_type in terminal + ] + if reached: + record["outcome"] = reached[-1] + if record["outcome"] == "completed": + record["trace"] = await handle.result() + break + await asyncio.sleep(0.1) + else: + record["outcome"] = "timed_out_waiting" + history = await handle.fetch_history() + + retried = [ + e + for e in history.events + if e.event_type == EventType.EVENT_TYPE_WORKFLOW_TASK_FAILED + ] + record["task_failures"] = [ + { + "event_id": e.event_id, + "cause": int(e.workflow_task_failed_event_attributes.cause), + "message": e.workflow_task_failed_event_attributes.failure.message, + } + for e in retried + ] + + try: + record["observed_output"] = await asyncio.wait_for(output, timeout=20) + except asyncio.TimeoutError: + output.cancel() + record["observed_output"] = "timed_out" + + async def receipts() -> list[Any]: + # Ends by itself once the workflow is closed and the tail served. + return [ + r.value + async for r in stream.read(topic=RECEIPTS) + if r.kind is RecordKind.DATA + ] + + try: + record["receipts"] = await asyncio.wait_for(receipts(), timeout=20) + except asyncio.TimeoutError: + record["receipts"] = "timed_out" + + history = await handle.fetch_history() + record["history_events"] = len(history.events) + (out / "history.json").write_text(history.to_json()) + await provider_setup.close(provider) + (out / "results.json").write_text(json.dumps(record, indent=2) + "\n") + print(json.dumps(record, indent=2)) + return 0 if record["outcome"] == "completed" else 1 + + +if __name__ == "__main__": + sys.exit(asyncio.run(main())) From 27385ea8e3a35bc6cffbc2ff3843522560db4f83 Mon Sep 17 00:00:00 2001 From: Mohammad Dashti Date: Sat, 3 Oct 2026 02:27:27 -0700 Subject: [PATCH 2/2] Removed a demo run's output from the streams demo. run_demo.py writes its results next to the script, and one run's output was committed with the sample. Ignored so a later run can't add it again. --- .gitignore | 3 + streams_demo/results-memory/history.json | 660 ----------------------- streams_demo/results-memory/results.json | 115 ---- 3 files changed, 3 insertions(+), 775 deletions(-) delete mode 100644 streams_demo/results-memory/history.json delete mode 100644 streams_demo/results-memory/results.json diff --git a/.gitignore b/.gitignore index 8cd439e05..15aa7014a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ temporalio/bridge/temporal_sdk_bridge* tags /.claude tmpclaude-* + +# Output of a streams_demo run, written next to the script. +streams_demo/results-*/ diff --git a/streams_demo/results-memory/history.json b/streams_demo/results-memory/history.json deleted file mode 100644 index b98211075..000000000 --- a/streams_demo/results-memory/history.json +++ /dev/null @@ -1,660 +0,0 @@ -{ - "events": [ - { - "eventId": "1", - "eventTime": "2026-10-03T08:56:51.314386Z", - "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED", - "taskId": "2105644", - "workflowExecutionStartedEventAttributes": { - "workflowType": { - "name": "StreamContractDemo" - }, - "taskQueue": { - "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "kind": "TASK_QUEUE_KIND_NORMAL" - }, - "input": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "OA==" - } - ] - }, - "workflowTaskTimeout": "10s", - "originalExecutionRunId": "01a100fa-fd72-75a9-8676-068fe15f9419", - "identity": "13139@Moes-MacBook-Pro.local", - "firstExecutionRunId": "01a100fa-fd72-75a9-8676-068fe15f9419", - "attempt": 1, - "firstWorkflowTaskBackoff": "0s", - "workflowId": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "priority": {} - } - }, - { - "eventId": "2", - "eventTime": "2026-10-03T08:56:51.326362Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", - "taskId": "2105645", - "workflowTaskScheduledEventAttributes": { - "taskQueue": { - "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "kind": "TASK_QUEUE_KIND_NORMAL" - }, - "startToCloseTimeout": "10s", - "attempt": 1 - } - }, - { - "eventId": "3", - "eventTime": "2026-10-03T08:56:51.372051Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", - "taskId": "2105650", - "workflowTaskStartedEventAttributes": { - "scheduledEventId": "2", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "425e75d3-cde6-4fd5-a9e7-7bd4270d26fe", - "historySizeBytes": "412", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "4", - "eventTime": "2026-10-03T08:56:51.442115Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", - "taskId": "2105655", - "workflowTaskCompletedEventAttributes": { - "scheduledEventId": "2", - "startedEventId": "3", - "identity": "13139@Moes-MacBook-Pro.local", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - }, - "sdkMetadata": { - "coreUsedFlags": [ - 3, - 1, - 2 - ], - "sdkName": "temporal-python", - "sdkVersion": "1.33.0" - }, - "meteringMetadata": {} - } - }, - { - "eventId": "5", - "eventTime": "2026-10-03T08:56:51.443333Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", - "taskId": "2105656", - "activityTaskScheduledEventAttributes": { - "activityId": "decision-r1", - "activityType": { - "name": "RecordDecision" - }, - "taskQueue": { - "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "kind": "TASK_QUEUE_KIND_NORMAL" - }, - "header": {}, - "input": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "eyJicmFuY2giOiJvZGQiLCJjb21wdXRlZCI6MTAxLCJzb3VyY2UiOiJyMSJ9" - } - ] - }, - "scheduleToCloseTimeout": "0s", - "scheduleToStartTimeout": "0s", - "startToCloseTimeout": "10s", - "heartbeatTimeout": "0s", - "workflowTaskCompletedEventId": "4", - "retryPolicy": { - "initialInterval": "1s", - "backoffCoefficient": 2.0, - "maximumInterval": "100s" - }, - "useWorkflowBuildId": true, - "priority": {} - } - }, - { - "eventId": "6", - "eventTime": "2026-10-03T08:56:51.443410Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", - "taskId": "2105660", - "activityTaskStartedEventAttributes": { - "scheduledEventId": "5", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "e2532e51-340a-460e-b7a4-df6926ef6ad4", - "attempt": 1, - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "7", - "eventTime": "2026-10-03T08:56:51.449160Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", - "taskId": "2105661", - "activityTaskCompletedEventAttributes": { - "result": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "InJlY29yZGVkOnIxOm9kZCI=" - } - ] - }, - "scheduledEventId": "5", - "startedEventId": "6", - "identity": "13139@Moes-MacBook-Pro.local" - } - }, - { - "eventId": "8", - "eventTime": "2026-10-03T08:56:51.449369Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", - "taskId": "2105662", - "workflowTaskScheduledEventAttributes": { - "taskQueue": { - "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", - "kind": "TASK_QUEUE_KIND_STICKY", - "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" - }, - "startToCloseTimeout": "10s", - "attempt": 1 - } - }, - { - "eventId": "9", - "eventTime": "2026-10-03T08:56:51.473693Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", - "taskId": "2105666", - "workflowTaskStartedEventAttributes": { - "scheduledEventId": "8", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "c9386a35-2f1b-48f8-9a4a-96dbb5ada323", - "historySizeBytes": "1317", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "10", - "eventTime": "2026-10-03T08:56:51.497035Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", - "taskId": "2105671", - "workflowTaskCompletedEventAttributes": { - "scheduledEventId": "8", - "startedEventId": "9", - "identity": "13139@Moes-MacBook-Pro.local", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - }, - "sdkMetadata": {}, - "meteringMetadata": {} - } - }, - { - "eventId": "11", - "eventTime": "2026-10-03T08:56:51.497094Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", - "taskId": "2105672", - "activityTaskScheduledEventAttributes": { - "activityId": "decision-r2", - "activityType": { - "name": "RecordDecision" - }, - "taskQueue": { - "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "kind": "TASK_QUEUE_KIND_NORMAL" - }, - "header": {}, - "input": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "eyJicmFuY2giOiJldmVuIiwiY29tcHV0ZWQiOjIwLCJzb3VyY2UiOiJyMiJ9" - } - ] - }, - "scheduleToCloseTimeout": "0s", - "scheduleToStartTimeout": "0s", - "startToCloseTimeout": "10s", - "heartbeatTimeout": "0s", - "workflowTaskCompletedEventId": "10", - "retryPolicy": { - "initialInterval": "1s", - "backoffCoefficient": 2.0, - "maximumInterval": "100s" - }, - "useWorkflowBuildId": true, - "priority": {} - } - }, - { - "eventId": "12", - "eventTime": "2026-10-03T08:56:51.497151Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", - "taskId": "2105675", - "activityTaskStartedEventAttributes": { - "scheduledEventId": "11", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "10718666-9e34-4cb8-a29b-5354b02b8478", - "attempt": 1, - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "13", - "eventTime": "2026-10-03T08:56:51.515418Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", - "taskId": "2105676", - "activityTaskCompletedEventAttributes": { - "result": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "InJlY29yZGVkOnIyOmV2ZW4i" - } - ] - }, - "scheduledEventId": "11", - "startedEventId": "12", - "identity": "13139@Moes-MacBook-Pro.local" - } - }, - { - "eventId": "14", - "eventTime": "2026-10-03T08:56:51.515466Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", - "taskId": "2105677", - "workflowTaskScheduledEventAttributes": { - "taskQueue": { - "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", - "kind": "TASK_QUEUE_KIND_STICKY", - "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" - }, - "startToCloseTimeout": "10s", - "attempt": 1 - } - }, - { - "eventId": "15", - "eventTime": "2026-10-03T08:56:51.517617Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", - "taskId": "2105681", - "workflowTaskStartedEventAttributes": { - "scheduledEventId": "14", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "6ae9c55e-9311-40e0-9769-252931cba559", - "historySizeBytes": "2192", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "16", - "eventTime": "2026-10-03T08:56:51.521729Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", - "taskId": "2105685", - "workflowTaskCompletedEventAttributes": { - "scheduledEventId": "14", - "startedEventId": "15", - "identity": "13139@Moes-MacBook-Pro.local", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - }, - "sdkMetadata": {}, - "meteringMetadata": {} - } - }, - { - "eventId": "17", - "eventTime": "2026-10-03T08:56:51.521779Z", - "eventType": "EVENT_TYPE_TIMER_STARTED", - "taskId": "2105686", - "timerStartedEventAttributes": { - "timerId": "1", - "startToFireTimeout": "0.100s", - "workflowTaskCompletedEventId": "16" - } - }, - { - "eventId": "18", - "eventTime": "2026-10-03T08:56:52.518155Z", - "eventType": "EVENT_TYPE_TIMER_FIRED", - "taskId": "2105689", - "timerFiredEventAttributes": { - "timerId": "1", - "startedEventId": "17" - } - }, - { - "eventId": "19", - "eventTime": "2026-10-03T08:56:52.518178Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", - "taskId": "2105690", - "workflowTaskScheduledEventAttributes": { - "taskQueue": { - "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", - "kind": "TASK_QUEUE_KIND_STICKY", - "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" - }, - "startToCloseTimeout": "10s", - "attempt": 1 - } - }, - { - "eventId": "20", - "eventTime": "2026-10-03T08:56:52.519801Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", - "taskId": "2105694", - "workflowTaskStartedEventAttributes": { - "scheduledEventId": "19", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "a50a8cea-96a3-434f-b5a3-13705af68b3f", - "historySizeBytes": "2661", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "21", - "eventTime": "2026-10-03T08:56:52.527177Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", - "taskId": "2105699", - "workflowTaskCompletedEventAttributes": { - "scheduledEventId": "19", - "startedEventId": "20", - "identity": "13139@Moes-MacBook-Pro.local", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - }, - "sdkMetadata": {}, - "meteringMetadata": {} - } - }, - { - "eventId": "22", - "eventTime": "2026-10-03T08:56:52.527217Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", - "taskId": "2105700", - "activityTaskScheduledEventAttributes": { - "activityId": "decision-r3", - "activityType": { - "name": "RecordDecision" - }, - "taskQueue": { - "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "kind": "TASK_QUEUE_KIND_NORMAL" - }, - "header": {}, - "input": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "eyJicmFuY2giOiJvZGQiLCJjb21wdXRlZCI6MTAzLCJzb3VyY2UiOiJyMyJ9" - } - ] - }, - "scheduleToCloseTimeout": "0s", - "scheduleToStartTimeout": "0s", - "startToCloseTimeout": "10s", - "heartbeatTimeout": "0s", - "workflowTaskCompletedEventId": "21", - "retryPolicy": { - "initialInterval": "1s", - "backoffCoefficient": 2.0, - "maximumInterval": "100s" - }, - "useWorkflowBuildId": true, - "priority": {} - } - }, - { - "eventId": "23", - "eventTime": "2026-10-03T08:56:52.527245Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", - "taskId": "2105703", - "activityTaskStartedEventAttributes": { - "scheduledEventId": "22", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "5f5f9ef8-699b-4caf-8272-ad1da4375db9", - "attempt": 1, - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "24", - "eventTime": "2026-10-03T08:56:52.530370Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", - "taskId": "2105704", - "activityTaskCompletedEventAttributes": { - "result": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "InJlY29yZGVkOnIzOm9kZCI=" - } - ] - }, - "scheduledEventId": "22", - "startedEventId": "23", - "identity": "13139@Moes-MacBook-Pro.local" - } - }, - { - "eventId": "25", - "eventTime": "2026-10-03T08:56:52.530382Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", - "taskId": "2105705", - "workflowTaskScheduledEventAttributes": { - "taskQueue": { - "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", - "kind": "TASK_QUEUE_KIND_STICKY", - "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" - }, - "startToCloseTimeout": "10s", - "attempt": 1 - } - }, - { - "eventId": "26", - "eventTime": "2026-10-03T08:56:52.534111Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", - "taskId": "2105709", - "workflowTaskStartedEventAttributes": { - "scheduledEventId": "25", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "33492902-eefb-43b1-9134-1ad6fa1bec84", - "historySizeBytes": "3535", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "27", - "eventTime": "2026-10-03T08:56:52.539976Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", - "taskId": "2105714", - "workflowTaskCompletedEventAttributes": { - "scheduledEventId": "25", - "startedEventId": "26", - "identity": "13139@Moes-MacBook-Pro.local", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - }, - "sdkMetadata": {}, - "meteringMetadata": {} - } - }, - { - "eventId": "28", - "eventTime": "2026-10-03T08:56:52.540016Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", - "taskId": "2105715", - "activityTaskScheduledEventAttributes": { - "activityId": "decision-r4", - "activityType": { - "name": "RecordDecision" - }, - "taskQueue": { - "name": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "kind": "TASK_QUEUE_KIND_NORMAL" - }, - "header": {}, - "input": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "eyJicmFuY2giOiJldmVuIiwiY29tcHV0ZWQiOjQwLCJzb3VyY2UiOiJyNCJ9" - } - ] - }, - "scheduleToCloseTimeout": "0s", - "scheduleToStartTimeout": "0s", - "startToCloseTimeout": "10s", - "heartbeatTimeout": "0s", - "workflowTaskCompletedEventId": "27", - "retryPolicy": { - "initialInterval": "1s", - "backoffCoefficient": 2.0, - "maximumInterval": "100s" - }, - "useWorkflowBuildId": true, - "priority": {} - } - }, - { - "eventId": "29", - "eventTime": "2026-10-03T08:56:52.540040Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", - "taskId": "2105718", - "activityTaskStartedEventAttributes": { - "scheduledEventId": "28", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "10c726d1-3b98-40ea-8cd1-35baaa53c605", - "attempt": 1, - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "30", - "eventTime": "2026-10-03T08:56:52.547729Z", - "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", - "taskId": "2105719", - "activityTaskCompletedEventAttributes": { - "result": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "InJlY29yZGVkOnI0OmV2ZW4i" - } - ] - }, - "scheduledEventId": "28", - "startedEventId": "29", - "identity": "13139@Moes-MacBook-Pro.local" - } - }, - { - "eventId": "31", - "eventTime": "2026-10-03T08:56:52.547747Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", - "taskId": "2105720", - "workflowTaskScheduledEventAttributes": { - "taskQueue": { - "name": "13139@Moes-MacBook-Pro.local-ae9afb70e5304b42944b95cc762ce2f2", - "kind": "TASK_QUEUE_KIND_STICKY", - "normalName": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1" - }, - "startToCloseTimeout": "10s", - "attempt": 1 - } - }, - { - "eventId": "32", - "eventTime": "2026-10-03T08:56:52.556472Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", - "taskId": "2105724", - "workflowTaskStartedEventAttributes": { - "scheduledEventId": "31", - "identity": "13139@Moes-MacBook-Pro.local", - "requestId": "2ae24ec7-e165-4ca9-8ead-bbd0523a7bb7", - "historySizeBytes": "4410", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - } - } - }, - { - "eventId": "33", - "eventTime": "2026-10-03T08:56:52.566679Z", - "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", - "taskId": "2105728", - "workflowTaskCompletedEventAttributes": { - "scheduledEventId": "31", - "startedEventId": "32", - "identity": "13139@Moes-MacBook-Pro.local", - "workerVersion": { - "buildId": "305b079191a1e625f49047e6956df64a" - }, - "sdkMetadata": {}, - "meteringMetadata": {} - } - }, - { - "eventId": "34", - "eventTime": "2026-10-03T08:56:52.566723Z", - "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED", - "taskId": "2105729", - "workflowExecutionCompletedEventAttributes": { - "result": { - "payloads": [ - { - "metadata": { - "encoding": "anNvbi9wbGFpbg==" - }, - "data": "W3sia2luZCI6ImRlY2lzaW9uIiwicmVjZWlwdCI6InJlY29yZGVkOnIxOm9kZCIsInZhbHVlIjp7ImJyYW5jaCI6Im9kZCIsImNvbXB1dGVkIjoxMDEsInNvdXJjZSI6InIxIn19LHsia2luZCI6ImRlY2lzaW9uIiwicmVjZWlwdCI6InJlY29yZGVkOnIyOmV2ZW4iLCJ2YWx1ZSI6eyJicmFuY2giOiJldmVuIiwiY29tcHV0ZWQiOjIwLCJzb3VyY2UiOiJyMiJ9fSx7ImF0dGVtcHQiOjIsImtpbmQiOiJzdXBlcnNlZGVkIiwicHJvZHVjZXIiOiJtb2RlbCIsInJlcGxhY2VkIjoxfSx7ImtpbmQiOiJkZWNpc2lvbiIsInJlY2VpcHQiOiJyZWNvcmRlZDpyMzpvZGQiLCJ2YWx1ZSI6eyJicmFuY2giOiJvZGQiLCJjb21wdXRlZCI6MTAzLCJzb3VyY2UiOiJyMyJ9fSx7ImtpbmQiOiJkZWNpc2lvbiIsInJlY2VpcHQiOiJyZWNvcmRlZDpyNDpldmVuIiwidmFsdWUiOnsiYnJhbmNoIjoiZXZlbiIsImNvbXB1dGVkIjo0MCwic291cmNlIjoicjQifX0seyJraW5kIjoiZmluaXNoIiwicHJvZHVjZXIiOiJtb2RlbCJ9XQ==" - } - ] - }, - "workflowTaskCompletedEventId": "33" - } - } - ] -} \ No newline at end of file diff --git a/streams_demo/results-memory/results.json b/streams_demo/results-memory/results.json deleted file mode 100644 index 1efcb3cb8..000000000 --- a/streams_demo/results-memory/results.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "provider": "memory", - "workflow_id": "ai198-contract-memory-1aae9812b18345dcbbfcb3cf5295edc1", - "target": "127.0.0.1:7943", - "max_cached_workflows": 512, - "outcome": "completed", - "trace": [ - { - "kind": "decision", - "receipt": "recorded:r1:odd", - "value": { - "branch": "odd", - "computed": 101, - "source": "r1" - } - }, - { - "kind": "decision", - "receipt": "recorded:r2:even", - "value": { - "branch": "even", - "computed": 20, - "source": "r2" - } - }, - { - "attempt": 2, - "kind": "superseded", - "producer": "model", - "replaced": 1 - }, - { - "kind": "decision", - "receipt": "recorded:r3:odd", - "value": { - "branch": "odd", - "computed": 103, - "source": "r3" - } - }, - { - "kind": "decision", - "receipt": "recorded:r4:even", - "value": { - "branch": "even", - "computed": 40, - "source": "r4" - } - }, - { - "kind": "finish", - "producer": "model" - } - ], - "task_failures": [], - "observed_output": [ - { - "kind": "DATA", - "value": { - "branch": "odd", - "computed": 101, - "source": "r1" - } - }, - { - "kind": "DATA", - "value": { - "branch": "even", - "computed": 20, - "source": "r2" - } - }, - { - "kind": "DATA", - "value": { - "retracting_attempt": 1 - } - }, - { - "kind": "DATA", - "value": { - "branch": "odd", - "computed": 103, - "source": "r3" - } - }, - { - "kind": "DATA", - "value": { - "branch": "even", - "computed": 40, - "source": "r4" - } - }, - { - "kind": "FINISH", - "value": null - } - ], - "receipts": [ - { - "receipt": "recorded:r1:odd" - }, - { - "receipt": "recorded:r2:even" - }, - { - "receipt": "recorded:r3:odd" - }, - { - "receipt": "recorded:r4:even" - } - ], - "history_events": 34 -}