Class: Protege::Responsibility

Inherits:
ApplicationRecord show all
Includes:
BroadcastableResponsibility
Defined in:
app/models/protege/responsibility.rb

Overview

A persona's standing, cron-scheduled duty — the record behind the Loop layer (the "L" of LOGI).

Where an inbound email drives the reactive path, a responsibility drives the proactive one: on its schedule (a 5-field cron string) the Loop scheduler runs the owning persona's responsibility_resolvers chain, seeded with this responsibility's instructions as the opening user turn. The persona decides what to do from there (typically sending mail via send_email).

Responsibilities are lean, dashboard-managed records — not a developer subclass; the per-persona resolver chain lives on the Persona, so a responsibility is just "which persona, what task, how often." Each execution is tracked by a ResponsibilityRun.

Constant Summary

Constants included from BroadcastableResponsibility

BroadcastableResponsibility::STREAM

Instance Method Summary collapse

Instance Method Details

#dispatch!Protege::ResponsibilityRun

Enqueue a run of this responsibility. Records a pending ResponsibilityRun now — its created_at marks enqueue time, so the later gap to the run's started_at surfaces a backed-up queue — then hands off to ResponsibilityJob, which advances it to running and on to completed/failed. No timestamp is taken here: nothing has run yet (the job stamps last_run_at).

The run's correlation_id is minted here, at birth, and the worker adopts it — so the whole lifecycle (+loop_run_enqueued+ → started → +completed+/+failed+) and the run row share one trace id. Protege::Current is set so the enqueued event carries it.

Returns:



77
78
79
80
81
82
83
84
# File 'app/models/protege/responsibility.rb', line 77

def dispatch!
  run                             = responsibility_runs.create!(status: :pending, correlation_id: SecureRandom.uuid)
  Protege::Current.correlation_id = run.correlation_id

  LoopRunEnqueuedEvent.emit(name:, persona_name: persona.name)
  ResponsibilityJob.perform_later(run_id: run.id)
  run
end

#due?(time) ⇒ Boolean

Whether this responsibility should fire at time — active and its cron matches that minute. The scheduler calls this each tick (over the with_active_persona set, so an archived persona's duties are already excluded); there is no precomputed next-run, only minute matching.

Parameters:

  • time (Time)

    the moment to test (the tick's Time.current)

Returns:

  • (Boolean)

    true when due



63
64
65
# File 'app/models/protege/responsibility.rb', line 63

def due?(time)
  active? && Loop.schedule_due?(schedule, at: time)
end