job-store.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
  2. import { join } from "node:path";
  3. import { tmpdir } from "node:os";
  4. export interface JobData {
  5. id: string;
  6. status: "pending" | "running" | "completed" | "failed";
  7. input: {
  8. text: string;
  9. template: string;
  10. platform?: string;
  11. platforms?: string[];
  12. ttsProvider: string;
  13. voiceId?: string;
  14. };
  15. error?: string;
  16. outputFiles?: Array<{
  17. filePath: string;
  18. fileSizeBytes: number;
  19. width: number;
  20. height: number;
  21. durationSeconds: number;
  22. }>;
  23. createdAt: number;
  24. updatedAt: number;
  25. }
  26. const STORE_DIR = join(tmpdir(), "pipeline-jobs");
  27. const STORE_FILE = join(STORE_DIR, "jobs.json");
  28. function ensureStore(): Map<string, JobData> {
  29. if (!existsSync(STORE_DIR)) {
  30. mkdirSync(STORE_DIR, { recursive: true });
  31. }
  32. if (!existsSync(STORE_FILE)) {
  33. writeFileSync(STORE_FILE, "{}", "utf-8");
  34. }
  35. try {
  36. const raw = readFileSync(STORE_FILE, "utf-8");
  37. const obj = JSON.parse(raw) as Record<string, JobData>;
  38. return new Map(Object.entries(obj));
  39. } catch {
  40. return new Map();
  41. }
  42. }
  43. function flushStore(jobs: Map<string, JobData>): void {
  44. const obj: Record<string, JobData> = {};
  45. for (const [k, v] of jobs) {
  46. obj[k] = v;
  47. }
  48. writeFileSync(STORE_FILE, JSON.stringify(obj), "utf-8");
  49. }
  50. export function getAllJobs(): JobData[] {
  51. const jobs = ensureStore();
  52. return Array.from(jobs.values()).sort(
  53. (a, b) => b.createdAt - a.createdAt
  54. );
  55. }
  56. export function getJob(id: string): JobData | undefined {
  57. const jobs = ensureStore();
  58. return jobs.get(id);
  59. }
  60. export function createJob(input: JobData["input"]): JobData {
  61. const jobs = ensureStore();
  62. const now = Date.now();
  63. const job: JobData = {
  64. id: crypto.randomUUID(),
  65. status: "pending",
  66. input,
  67. createdAt: now,
  68. updatedAt: now,
  69. };
  70. jobs.set(job.id, job);
  71. flushStore(jobs);
  72. return job;
  73. }
  74. export function updateJob(id: string, updates: Partial<JobData>): JobData | undefined {
  75. const jobs = ensureStore();
  76. const job = jobs.get(id);
  77. if (!job) return undefined;
  78. Object.assign(job, updates, { updatedAt: Date.now() });
  79. flushStore(jobs);
  80. return job;
  81. }