Ctrl K
ComunidadGuías…

lib/autonomous-run-scheduler.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
var sessionProvenance = require("./session-provenance");

function attachAutonomousRunScheduler(ctx) {
  var scheduler = ctx.scheduler;
  var type = "autonomous-wake:" + ctx.projectId;
  var unregister = null;
  function isMultiUser() { return typeof ctx.isMultiUser === "function" ? ctx.isMultiUser() : !!ctx.isMultiUser; }

  function origin(session) {
    var existing = session.sessionOriginId;
    var value = sessionProvenance.ensureOrigin(session);
    if (!existing) ctx.sm.saveSessionFile(session);
    return value;
  }
  function owner(session) {
    if (isMultiUser()) {
      if (!session.ownerId) throw new Error("Until complete requires an explicit session owner.");
      return session.ownerId;
    }
    return "local-user";
  }
  function matching(job, session, run, kind) {
    return job.type === type && job.projectId === ctx.projectId && job.target.id === origin(session) &&
      job.payload.runId === run.id && (!kind || job.payload.kind === kind);
  }
  function queued(session, run, kind) {
    var jobs = scheduler.listJobs();
    for (var i = jobs.length - 1; i >= 0; i--) if (jobs[i].state === "queued" && matching(jobs[i], session, run, kind)) return jobs[i];
    return null;
  }
  function schedule(session, run, kind, runAt) {
    var sessionOrigin = origin(session);
    run.wakeSequence = Math.max(0, Math.floor(Number(run.wakeSequence) || 0)) + 1;
    if (ctx.sm && typeof ctx.sm.saveSessionFile === "function") ctx.sm.saveSessionFile(session);
    var spec = {
      type: type,
      idempotencyKey: "autonomous:" + sessionOrigin + ":" + run.id + ":" + kind + ":" + run.cancellationEpoch + ":" + run.wakeSequence,
      ownerId: owner(session),
      projectId: ctx.projectId,
      target: { kind: "project-session-origin", id: sessionOrigin },
      payload: { kind: kind, runId: run.id, epoch: run.cancellationEpoch, wakeSequence: run.wakeSequence, sessionOrigin: sessionOrigin, cliSessionId: session.cliSessionId || null },
      runAt: Number(runAt),
    };
    var current = queued(session, run, kind);
    return current ? scheduler.replaceQueued(current.id, spec) : scheduler.enqueue(spec);
  }
  function cancel(session, run, kinds) {
    if (!run) return;
    var jobs = scheduler.listJobs();
    for (var i = 0; i < jobs.length; i++) {
      if (jobs[i].state !== "queued" || !matching(jobs[i], session, run)) continue;
      if (kinds && kinds.indexOf(jobs[i].payload.kind) === -1) continue;
      scheduler.cancel(jobs[i].id, "autonomous_run_cancelled_or_replaced");
    }
  }
  function findSession(job) {
    var found = null;
    ctx.sm.sessions.forEach(function (session) {
      if (!found && session.sessionOriginId === job.target.id) found = session;
    });
    return found;
  }
  function exact(job) {
    var session = findSession(job);
    var run = session && session.autonomousRun;
    if (!session || !run || run.id !== job.payload.runId) return null;
    if (job.payload.kind !== "deadline" && owner(session) !== job.ownerId) return null;
    if (Number(run.cancellationEpoch || 0) !== Number(job.payload.epoch)) return null;
    if (run.state === "armed" || run.state === "paused" || ["completed", "stopped", "limit", "error"].indexOf(run.state) !== -1) return null;
    if (job.payload.kind !== "deadline" && ctx.authorize && !ctx.authorize(session)) return null;
    return { session: session, run: run };
  }
  function canRun(job) {
    var current;
    try { current = exact(job); } catch (error) { return true; }
    if (!current) return true;
    return job.payload.kind !== "continuation" || (!current.session.isProcessing && !current.session._queryStarting);
  }
  function dispatch(job, execution) {
    var current = exact(job);
    if (!current) throw new Error("The Until complete wake no longer belongs to an authorized active run.");
    execution.recordMetadata({ projectId: ctx.projectId, runId: current.run.id, kind: job.payload.kind, sessionOrigin: job.target.id, epoch: job.payload.epoch });
    execution.recordReceipt({ state: "dispatching", runId: current.run.id, kind: job.payload.kind, sessionOrigin: job.target.id, recordedAt: Date.now() });
    return ctx.onWake(job.payload.kind, current.session, current.run);
  }
  function start() {
    if (!unregister) unregister = scheduler.registerHandler(type, dispatch, { canRun: canRun });
  }
  return { schedule: schedule, cancel: cancel, start: start, shutdown: function () { if (unregister) { unregister(); unregister = null; } } };
}

module.exports = { attachAutonomousRunScheduler: attachAutonomousRunScheduler };