Mirror Neuron Documents

Schedules And Events

Documentation for Schedules And Events.

Schedules And Events

MirrorNeuron runtime now owns periodic, delayed, and event-triggered jobs. This moves scheduling authority out of OtterDesk and into the same runtime layer that already understands resources, services, deployments, and restart/reschedule policy.

Scheduled child jobs are ordinary MirrorNeuron jobs. They get normal reconciliation, resource placement, service preflight, deployment metadata, and reliability behavior.

Design Concept

Schedules are Redis records with:

  • schedule_id
  • kind: periodic, delayed, or event
  • bundle reference and manifest snapshot
  • enabled/status state
  • timezone
  • next_run_at
  • last dispatch state
  • child job ids
  • source metadata
  • missed/failure counters

The cluster leader processes due schedules. Per-schedule leases and idempotency keys prevent duplicate dispatch when local and remote nodes are both alive.

Event triggers are declarative. They match event type and payload filters. They do not execute code in the trigger itself.

Periodic Jobs

Manifest shape:

{
  "schedule": {
    "enabled": true,
    "kind": "periodic",
    "crons": ["0 2 * * *"],
    "timezone": "America/New_York",
    "prohibit_overlap": true,
    "missed_policy": "skip",
    "catchup_limit": 10,
    "window": {
      "duration_ms": 3600000,
      "end_action": "cancel"
    }
  }
}

Create a periodic schedule:

mn schedule create /path/to/bundle \
  --cron "0 2 * * *" \
  --timezone America/New_York \
  --name nightly-eval

Allow overlapping child jobs:

mn schedule create /path/to/bundle --cron "*/15 * * * *" --allow-overlap

Create a bounded window:

mn schedule create /path/to/bundle --cron "0 1 * * *" --window 2h

Supported cron shortcuts:

  • @hourly
  • @daily
  • @weekly
  • @monthly
  • @yearly
  • @annually

Five-field cron syntax is also supported.

Delayed Jobs

Run once at an exact time:

mn schedule delay /path/to/bundle --at "2026-05-25T02:00:00Z"

Run once after a delay:

mn schedule delay /path/to/bundle --in 30m --name delayed-cleanup

Manifest shape:

{
  "schedule": {
    "kind": "delayed",
    "run_at": "2026-05-25T02:00:00Z"
  }
}

or:

{
  "schedule": {
    "kind": "delayed",
    "delay_ms": 1800000
  }
}

Event-Triggered Jobs

Create an event trigger:

mn trigger create /path/to/bundle \
  --event file_uploaded \
  --filter-json '{"path":{"prefix":"/datasets/"}}'

Emit an event:

mn event emit file_uploaded \
  --payload-json '{"path":"/datasets/eval.jsonl","bucket":"local"}'

Manifest trigger shape:

{
  "triggers": [
    {
      "name": "dataset-uploaded",
      "enabled": true,
      "event_type": "file_uploaded",
      "filters": {
        "path": {
          "prefix": "/datasets/"
        }
      }
    }
  ]
}

Filter values can match exact values, lists, string prefixes, and string contains:

{
  "source": "otterdesk",
  "path": {
    "contains": ".jsonl"
  },
  "kind": ["dataset", "eval"]
}

Schedule Operations

List schedules:

mn schedule list
mn schedule list --kind periodic
mn schedule list --status active

Show status:

mn schedule status <schedule-id>

Pause and resume:

mn schedule pause <schedule-id> --reason "hold during maintenance"
mn schedule resume <schedule-id> --reason "maintenance complete"

Dispatch immediately:

mn schedule run-now <schedule-id>
mn schedule run-now <schedule-id> --payload-json '{"manual":true}'

Delete:

mn schedule delete <schedule-id> --reason "retired"

List trigger events:

mn event list --limit 50

Missed Runs And Overlap

prohibit_overlap defaults to true. When a previous child job is still active, the schedule does not launch another overlapping child unless overlap is explicitly allowed.

missed_policy controls late periodic runs:

PolicyBehavior
skipSkip runs that are past the missed grace.
catchup_oneDispatch one missed run.
catchup_allDispatch missed runs up to catchup_limit.

The default timezone is UTC. The CLI sends the local timezone explicitly unless you pass --timezone.

OtterDesk Adoption

OtterDesk is now a schedule client:

  • GUI and CLI schedule actions create or update MirrorNeuron runtime schedules
  • OtterDesk stores the runtime schedule_id
  • status displays runtime next_run_at, last dispatch, and errors
  • upload flows emit runtime events such as bundle_uploaded and file_uploaded
  • local schedule utilities remain for preview and conflict hints, not for launching jobs

Important Code

AreaFiles
Policy normalization and cron/event matchingMirrorNeuron/lib/mirror_neuron/runtime/schedule_policy.ex
Schedule dispatch and due processingMirrorNeuron/lib/mirror_neuron/runtime/schedule_dispatcher.ex
Leader sweepsMirrorNeuron/lib/mirror_neuron/cluster/leader.ex
Redis schedule/event storageMirrorNeuron/lib/mirror_neuron/persistence/redis_store.ex
gRPC methodsMirrorNeuron/lib/mirror_neuron_grpc/server.ex
CLI commandsmn-cli/mn_cli/libs/schedule_cmds.py
SDK client and decoratorsmn-python-sdk/mn_sdk/client.py, mn-python-sdk/mn_sdk/decorators.py, mn-python-sdk/mn_sdk/bundle.py
REST API emittersmn-api upload and schedule endpoints
OtterDesk schedule clientotterdesk-desktop-app scheduler and GUI schedule code

V1 Limits

  • schedules dispatch normal child jobs; they are not a separate execution engine
  • event triggers use declarative filters only
  • cron parsing is five-field minute-level syntax plus common shortcuts
  • upload events are a built-in event source, but event types are otherwise generic

On this page