Eventum Logo

Eventum

Eventtemplate

Dispatch

Control whether an event is produced, skipped, or generation is stopped.

Sometimes a template should not produce an event — for example, when a session pool is empty or a finite dataset is exhausted. The dispatch object provides three actions that let templates control this behavior at render time.

dispatch.drop()

Skips the current event entirely. No output is produced for this timestamp, and the dropped counter is incremented in the monitoring panel.

Picker state (spin index, FSM state, chain position) is not rolled back — the pick already happened, only the output is discarded.

{%- set sessions = shared.get('sessions', []) -%}
{%- if sessions | length == 0 -%}
  {%- do dispatch.drop() -%}
{%- endif -%}
{%- set sess = sessions.pop(0) -%}
{%- do shared.set('sessions', sessions) -%}
{"session": "{{ sess.id }}", "timestamp": "{{ timestamp.isoformat() }}"}

When there are no sessions to consume, the event is silently dropped instead of producing an incomplete record.

In all mode, if any template calls dispatch.drop(), the output from all templates is discarded — including templates that already rendered successfully before the drop.


dispatch.next()

Discards the current output and asks the generator to pick templates again for the same timestamp. This is useful when the selected template cannot produce a meaningful event but another one might.

What happens on re-pick depends on the picking mode:

ModeWhat happens
allAll templates are picked and rendered again from scratch.
any / chanceA new random pick is made.
spin / chainThe position advances to the next template.
fsmTransitions are re-evaluated with the updated state.

Parameters

ParameterTypeDefaultDescription
max_repicksint64Maximum number of re-pick attempts for one timestamp. Must be at least 1.

If the limit is reached, the event fails with an error.

{%- set pool = shared.get('pool', []) -%}
{%- if pool | length == 0 -%}
  {%- do dispatch.next(max_repicks=10) -%}
{%- endif -%}
{%- set item = pool.pop(0) -%}
{%- do shared.set('pool', pool) -%}
{"item": "{{ item }}"}

If every possible template calls dispatch.next(), the re-pick limit will be reached and the event will fail. Make sure at least one reachable template can produce output.


dispatch.exhaust()

Signals that the generator has finished producing events. The generator shuts down gracefully and no more timestamps are processed.

This is useful for finite generation scenarios — for example, replaying a fixed dataset or generating an exact number of correlated sessions.

{%- set remaining = shared.get('remaining', 100) -%}
{%- if remaining <= 0 -%}
  {%- do dispatch.exhaust() -%}
{%- endif -%}
{%- do shared.set('remaining', remaining - 1) -%}
{"count": {{ remaining }}, "timestamp": "{{ timestamp.isoformat() }}"}

In all mode, if any template calls dispatch.exhaust(), remaining templates in the batch are not rendered.


State and dispatch

Dispatch actions do not roll back state changes. Any values written to locals, shared, or globals before a dispatch call remain in effect.

{%- do shared.set('marker', 'written') -%}
{%- do dispatch.drop() -%}

After this template runs, shared.get('marker') returns 'written' even though no event was produced.

Best practice: always check preconditions before mutating state. If you modify state first and then drop, the change is permanent even though the event was discarded.

{%- set sessions = shared.get('sessions', []) -%}
{# Check BEFORE mutating #}
{%- if sessions | length == 0 -%}
  {%- do dispatch.drop() -%}
{%- endif -%}
{# Safe to mutate - we know sessions is non-empty #}
{%- set sess = sessions.pop(0) -%}
{%- do shared.set('sessions', sessions) -%}

On this page