Skip to main content

RabbitMQ Activities

Two activities: rabbit.publish sends a message to a topic, and rabbit.receive subscribes to one and feeds each message into the running workflow as an event.

This is the most convenient way to drive a long-running workflow from an outside system — a workflow parked in wait_for wakes up when something publishes to its topic.

Setup

The connection URL comes from the connection_url input field or, when that is unset, from MOCO_RMQ_CONNECTION_URL. Credentials are embedded in the URL; there is no secret-store integration for this provider.

The same variable enables debug streaming

MOCO_RMQ_CONNECTION_URL also backs the debug event bus. A deployment without it loses live run output and builtin.event.emit_debug_event as well.

Defaults

ActivityTimeoutMax attemptsHeartbeatAsync by default
rabbit.publish60 s3no
rabbit.receive~10 years0 — unlimited20 s interval / 60 s timeoutyes

rabbit.publish

Publishes one message to a topic.

Input

FieldTypeRequiredDefaultDescription
topicstryesDestination topic
dataanyyesMessage payload
event_typestrnonullEvent type stamped on the message
sourcestrnonullFree-text origin label
metadatadictnonullExtra metadata carried with the message
connection_urlstrnoMOCO_RMQ_CONNECTION_URLAMQP connection URL
exchangestrnodefault exchangeExchange to publish through

Output

FieldTypeDescription
publishedboolAlways true
topicstrThe topic published to

Example

From moco-examples/rmq-demo/src/rmq-publish.yaml:

- activity:
type: rabbit.publish
input_data:
topic: "{{ source_topic }}"
event_type: "{{ event_type }}"
data: "{{ message }}"
output_name: publish_result

rabbit.receive

Subscribes to a topic and relays each message into the running workflow as an event, which the workflow picks up with wait_for. It runs until the activity is cancelled.

Unlike every other long-running activity, this one defaults to async mode — you do not have to remember async_mode: true, and it will not block your workflow.

Input

FieldTypeRequiredDefaultDescription
topicstryesRabbitMQ topic to subscribe to
connection_urlstrnoMOCO_RMQ_CONNECTION_URLAMQP connection URL
exchangestrnodefault exchangeExchange to bind to
relay_topicstrno"default"Event topic the workflow listens on
relay_event_typestrnonullevent_type stamped on each relayed event
target_workflow_idstrnocurrent workflowWorkflow the events are delivered to

Output

Returned when the activity is cancelled:

FieldTypeDescription
stoppedboolAlways true
receivedintMessages relayed during the run

Relayed event data

Each message arrives at wait_for as an event whose data is:

FieldTypeDescription
topicstrSource RabbitMQ topic
dataanyThe published payload
event_typestr | nullEvent type from the publisher
metadatadict | nullMetadata from the publisher

Example

From moco-examples/rmq-demo/src/rmq-demo.yaml:

- activity:
type: rabbit.receive
async_mode: true # non-blocking; keeps relaying in the background
input_data:
topic: "demo_topic" # RabbitMQ source topic
relay_topic: "demo_topic" # == event_source_topic
relay_event_type: "rmq_message"
target_workflow_id: "{{ __sys_info__['workflow_id'] }}"
- wait_for:
event_source_topic: "demo_topic"
event_type: "rmq_message"
timeout_sec: 600
output_name: incoming

- transform:
output_data:
- payload: "{{ incoming['data']['data'] }}"
An unreachable broker retries forever

rabbit.receive ships max_attempts: 0, meaning unlimited retries, so a subscriber survives a broker restart without operator action. The flip side: a wrong connection_url produces an infinite retry loop rather than a failure. Liveness comes from the 60-second heartbeat, not from the ten-year timeout.

Every message costs workflow history

On the Temporal runtime each relayed message is a workflow signal and a history entry, and the engine keeps at most 1000 unmatched events per topic. Keep the topic low-rate, and make sure a wait_for is actually consuming the events.