0018_project_schedules.sql 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. -- 0018_project_schedules — cron-triggered function invocations.
  2. -- The dispatcher worker (apps/api/src/workers/schedule-dispatcher.ts)
  3. -- runs every 60s, selects rows where enabled and next_run_at <= now()
  4. -- using the partial index below, and bumps next_run_at forward in the
  5. -- same UPDATE that records the run outcome — optimistic claim with no
  6. -- explicit lock needed.
  7. CREATE TABLE IF NOT EXISTS "project_schedules" (
  8. "id" text PRIMARY KEY NOT NULL,
  9. "project_id" text NOT NULL,
  10. "name" text NOT NULL,
  11. "function_name" text NOT NULL,
  12. "cron_expression" text NOT NULL,
  13. "args" jsonb DEFAULT '{}'::jsonb NOT NULL,
  14. "enabled" boolean DEFAULT true NOT NULL,
  15. "next_run_at" timestamp with time zone NOT NULL,
  16. "last_run_at" timestamp with time zone,
  17. "last_run_status" text,
  18. "last_run_error" text,
  19. "created_by" text,
  20. "created_at" timestamp with time zone DEFAULT now() NOT NULL,
  21. "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
  22. "deleted_at" timestamp with time zone,
  23. CONSTRAINT "project_schedules_project_id_fk"
  24. FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE,
  25. CONSTRAINT "project_schedules_created_by_fk"
  26. FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL
  27. );
  28. -- Unique per project among non-deleted rows. Soft-deleted schedules
  29. -- don't block a customer from reusing a name.
  30. CREATE UNIQUE INDEX IF NOT EXISTS "project_schedules_project_name_idx"
  31. ON "project_schedules" USING btree ("project_id", "name")
  32. WHERE "deleted_at" IS NULL;
  33. -- Dispatcher hot path: enabled + due rows only.
  34. CREATE INDEX IF NOT EXISTS "project_schedules_due_idx"
  35. ON "project_schedules" USING btree ("next_run_at")
  36. WHERE "enabled" = true AND "deleted_at" IS NULL;