| 123456789101112131415161718192021222324252627282930313233343536373839 |
- -- 0018_project_schedules — cron-triggered function invocations.
- -- The dispatcher worker (apps/api/src/workers/schedule-dispatcher.ts)
- -- runs every 60s, selects rows where enabled and next_run_at <= now()
- -- using the partial index below, and bumps next_run_at forward in the
- -- same UPDATE that records the run outcome — optimistic claim with no
- -- explicit lock needed.
- CREATE TABLE IF NOT EXISTS "project_schedules" (
- "id" text PRIMARY KEY NOT NULL,
- "project_id" text NOT NULL,
- "name" text NOT NULL,
- "function_name" text NOT NULL,
- "cron_expression" text NOT NULL,
- "args" jsonb DEFAULT '{}'::jsonb NOT NULL,
- "enabled" boolean DEFAULT true NOT NULL,
- "next_run_at" timestamp with time zone NOT NULL,
- "last_run_at" timestamp with time zone,
- "last_run_status" text,
- "last_run_error" text,
- "created_by" text,
- "created_at" timestamp with time zone DEFAULT now() NOT NULL,
- "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
- "deleted_at" timestamp with time zone,
- CONSTRAINT "project_schedules_project_id_fk"
- FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE,
- CONSTRAINT "project_schedules_created_by_fk"
- FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL
- );
- -- Unique per project among non-deleted rows. Soft-deleted schedules
- -- don't block a customer from reusing a name.
- CREATE UNIQUE INDEX IF NOT EXISTS "project_schedules_project_name_idx"
- ON "project_schedules" USING btree ("project_id", "name")
- WHERE "deleted_at" IS NULL;
- -- Dispatcher hot path: enabled + due rows only.
- CREATE INDEX IF NOT EXISTS "project_schedules_due_idx"
- ON "project_schedules" USING btree ("next_run_at")
- WHERE "enabled" = true AND "deleted_at" IS NULL;
|