{"files": {"main.ts": "import {run} from './core.ts';\nimport {POLICY} from './policy.ts';\nexport function evaluate(payload: any): any { return run(payload, POLICY); }\n", "core.ts": "import {dedupeJobs, computeEffectiveDue} from './helpers.ts';\nexport function run(payload: any, policy: any): any {\n  const now: number = payload.now;\n  const jobs: any[] = payload.jobs || [];\n  const retryableCodes: any[] = policy.retryable_codes || [];\n  const retryableSet = new Set(retryableCodes);\n  const selected: any[] = dedupeJobs(jobs, policy.dedup_key);\n  const ready: any[] = [];\n  const waiting: any[] = [];\n  const dead: any[] = [];\n  const cancelled: any[] = [];\n  for (const entry of selected) {\n    const job: any = entry.job;\n    const retryable: boolean = retryableSet.has(job.last_code);\n    if (job.cancelled && (policy.cancel_wins || !retryable)) {\n      cancelled.push(entry);\n      continue;\n    }\n    const stale: boolean = policy.stale_inclusive ? (now - job.created >= policy.stale_after) : (now - job.created > policy.stale_after);\n    if (stale || job.attempt >= policy.max_attempts || (job.last_code !== 0 && !retryable)) {\n      dead.push(entry);\n      continue;\n    }\n    const effectiveDue: number = computeEffectiveDue(job, retryable, policy);\n    if (effectiveDue > now) {\n      waiting.push({job: job, index: entry.index, at: effectiveDue});\n    } else {\n      ready.push(entry);\n    }\n  }\n  ready.sort((a: any, b: any) => {\n    if (a.job.priority !== b.job.priority) {\n      return policy.priority_high_first ? (b.job.priority - a.job.priority) : (a.job.priority - b.job.priority);\n    }\n    if (a.job.created !== b.job.created) {\n      return policy.fifo_ties ? (a.job.created - b.job.created) : (b.job.created - a.job.created);\n    }\n    return a.index - b.index;\n  });\n  dead.sort((a: any, b: any) => {\n    if (policy.dead_order === 'id') {\n      if (a.job.id < b.job.id) return -1;\n      if (a.job.id > b.job.id) return 1;\n      return a.index - b.index;\n    }\n    return a.index - b.index;\n  });\n  waiting.sort((a: any, b: any) => a.index - b.index);\n  cancelled.sort((a: any, b: any) => a.index - b.index);\n  return {\n    ready: ready.map((e: any) => e.job.id),\n    waiting: waiting.map((e: any) => ({id: e.job.id, at: e.at})),\n    dead: dead.map((e: any) => e.job.id),\n    cancelled: cancelled.map((e: any) => e.job.id)\n  };\n}\n", "policy.ts": "export const POLICY: any = {\"base_delay\": 200, \"cancel_wins\": false, \"dead_order\": \"input\", \"dedup_key\": \"key\", \"delay_cap\": 400, \"exponential\": false, \"fifo_ties\": false, \"max_attempts\": 4, \"priority_high_first\": false, \"retryable_codes\": [408, 503], \"stale_after\": 2000, \"stale_inclusive\": false};\n", "helpers.ts": "export function dedupeJobs(jobs: any[], dedupKey: string): any[] {\n  const byKey = new Map<any, any>();\n  jobs.forEach((job: any, index: number) => {\n    byKey.set(job[dedupKey], {job: job, index: index});\n  });\n  return Array.from(byKey.values());\n}\nexport function computeEffectiveDue(job: any, retryable: boolean, policy: any): number {\n  if (!retryable) {\n    return job.due;\n  }\n  const factor: number = policy.exponential ? Math.pow(2, Math.max(0, job.attempt - 1)) : 1;\n  const delay: number = Math.min(policy.base_delay * factor, policy.delay_cap);\n  return Math.max(job.due, job.failed_at + delay);\n}\n"}}