@nest-batch/typeorm 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +55 -0
- package/README.md +27 -234
- package/dist/src/entities/job-meta.entities.d.ts +2 -2
- package/dist/src/entities/job-meta.entities.d.ts.map +1 -1
- package/dist/src/entities/job-meta.entities.js +3 -4
- package/dist/src/entities/job-meta.entities.js.map +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +13 -6
- package/dist/src/index.js.map +1 -1
- package/dist/src/repository/typeorm-job-repository.d.ts +2 -2
- package/dist/src/repository/typeorm-job-repository.d.ts.map +1 -1
- package/dist/src/repository/typeorm-job-repository.js.map +1 -1
- package/package.json +5 -4
- package/src/entities/job-meta.entities.ts +5 -6
- package/src/index.ts +10 -6
- package/src/repository/typeorm-job-repository.ts +109 -75
- package/dist/src/migrations/1700000000000-CreateBatchMeta.d.ts +0 -28
- package/dist/src/migrations/1700000000000-CreateBatchMeta.d.ts.map +0 -1
- package/dist/src/migrations/1700000000000-CreateBatchMeta.js +0 -83
- package/dist/src/migrations/1700000000000-CreateBatchMeta.js.map +0 -1
- package/src/migrations/1700000000000-CreateBatchMeta.ts +0 -100
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/repository/typeorm-job-repository.ts"],"sourcesContent":["import { Inject, Injectable } from '@nestjs/common';\nimport { randomUUID } from 'node:crypto';\nimport { DataSource, EntityManager, In } from 'typeorm';\nimport {\n JobRepository,\n JobExecutionAlreadyRunningError,\n assertJsonSerializable,\n serializeContext,\n deserializeContext,\n JobStatus,\n StepStatus,\n} from '@nest-batch/core';\nimport type {\n JobInstance,\n JobExecution,\n JobExecutionPatch,\n JobParameters,\n StepExecution,\n StepExecutionPatch,\n ExecutionContext,\n ExecutionScope,\n JobInstanceFilter,\n JobExecutionFilter,\n} from '@nest-batch/core';\nimport { TypeOrmDriverProvider } from '../typeorm.driver-provider';\n\nfunction scopeKey(scope: ExecutionScope): string {\n if ('jobExecutionId' in scope) return `job::${scope.jobExecutionId}`;\n return `step::${scope.stepExecutionId}`;\n}\n\nfunction deepClone<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value;\n if (value instanceof Date) return new Date(value.getTime()) as unknown as T;\n if (Array.isArray(value)) return value.map((v) => deepClone(v)) as unknown as T;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>)) {\n out[k] = deepClone((value as Record<string, unknown>)[k]);\n }\n return out as T;\n}\n\ninterface JobInstanceRow {\n id: string;\n job_name: string;\n job_key: string;\n created_at: string | Date;\n}\n\ninterface JobExecutionRow {\n id: string;\n job_instance_id: string;\n status: string;\n start_time: string | Date | null;\n end_time: string | Date | null;\n exit_code: string;\n exit_message: string;\n params: string;\n}\n\ninterface StepExecutionRow {\n id: string;\n job_execution_id: string;\n step_name: string;\n status: string;\n read_count: number;\n write_count: number;\n skip_count: number;\n rollback_count: number;\n commit_count: number;\n exit_code: string;\n exit_message: string;\n created_at: string | Date;\n}\n\ninterface ContextRow {\n data: string;\n version: number;\n}\n\nfunction mapJobInstance(r: JobInstanceRow): JobInstance {\n return {\n id: r.id,\n jobName: r.job_name,\n jobKey: r.job_key,\n createdAt: r.created_at instanceof Date ? r.created_at : new Date(r.created_at),\n };\n}\n\nfunction mapJobExecution(r: JobExecutionRow): JobExecution {\n let params: JobParameters = {};\n if (r.params && r.params.length > 0) {\n try {\n params = deserializeContext<JobParameters>(r.params);\n } catch {\n params = {};\n }\n }\n return {\n id: r.id,\n jobInstanceId: r.job_instance_id,\n status: r.status as JobStatus,\n startTime: r.start_time ? (r.start_time instanceof Date ? r.start_time : new Date(r.start_time)) : null,\n endTime: r.end_time ? (r.end_time instanceof Date ? r.end_time : new Date(r.end_time)) : null,\n exitCode: r.exit_code,\n exitMessage: r.exit_message,\n params,\n };\n}\n\nfunction mapStepExecution(r: StepExecutionRow): StepExecution {\n return {\n id: r.id,\n jobExecutionId: r.job_execution_id,\n stepName: r.step_name,\n status: r.status as StepStatus,\n readCount: r.read_count,\n writeCount: r.write_count,\n skipCount: r.skip_count,\n rollbackCount: r.rollback_count,\n commitCount: r.commit_count,\n startTime: null,\n endTime: null,\n exitCode: r.exit_code,\n exitMessage: r.exit_message,\n };\n}\n\n/**\n * TypeORM 1.0.0-backed `JobRepository`.\n *\n * The package is driver-agnostic: the actual `DataSource` is\n * provided by the `@nest-batch/postgresql` (or future\n * `@nest-batch/mysql`) driver sibling via the `TypeOrmDriverProvider`\n * token. The repository itself uses raw SQL via `EntityManager.query`\n * so the column-shape contract is owned by the driver sibling\n * (the bundled 6-table migration).\n *\n * The contract guarantees:\n * - `getOrCreateJobInstance` is race-safe via the (jobName, jobKey)\n * unique index.\n * - `createExecutionAtomic` runs inside a single transaction that\n * (a) idempotently upserts the instance row, (b) acquires a row\n * lock with `SELECT ... FOR UPDATE SKIP LOCKED` (PostgreSQL) or\n * a plain select (SQLite test driver), and (c) rejects with\n * `JobExecutionAlreadyRunningError` if a STARTING/STARTED\n * execution already exists.\n * - `saveExecutionContext` deep-clones the data and auto-increments\n * the version counter when `version` is omitted.\n * - `findLatestStepExecution` orders by `created_at` descending.\n */\n@Injectable()\nexport class TypeOrmJobRepository extends JobRepository {\n constructor(\n @Inject(TypeOrmDriverProvider) private readonly dataSource: DataSource,\n ) {\n super();\n }\n\n private em(): EntityManager {\n return this.dataSource.manager;\n }\n\n async getOrCreateJobInstance(name: string, jobKey: string): Promise<JobInstance> {\n const existing = await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n LIMIT 1`,\n [name, jobKey],\n ) as JobInstanceRow[];\n if (existing.length > 0) return mapJobInstance(existing[0]!);\n\n const id = randomUUID();\n try {\n const inserted = await this.em().query(\n `INSERT INTO \"batch_job_instance\" (\"id\", \"job_name\", \"job_key\", \"created_at\")\n VALUES ($1, $2, $3, NOW())\n ON CONFLICT (\"job_name\", \"job_key\") DO NOTHING\n RETURNING \"id\", \"job_name\", \"job_key\", \"created_at\"`,\n [id, name, jobKey],\n ) as JobInstanceRow[];\n if (inserted.length > 0) return mapJobInstance(inserted[0]!);\n } catch {\n // Fall through to read-back.\n }\n const winner = await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n LIMIT 1`,\n [name, jobKey],\n ) as JobInstanceRow[];\n if (winner.length === 0) {\n throw new Error(\n `Failed to upsert JobInstance (${name}, ${jobKey}) and could not read it back`,\n );\n }\n return mapJobInstance(winner[0]!);\n }\n\n async createJobExecution(\n jobInstanceId: string,\n params: JobParameters,\n ): Promise<JobExecution> {\n const exec = {\n id: randomUUID(),\n job_instance_id: jobInstanceId,\n status: JobStatus.STARTING,\n start_time: null as Date | null,\n end_time: null as Date | null,\n exit_code: '',\n exit_message: '',\n params: serializeContext(deepClone(params)),\n };\n const rows = await this.em().query(\n `INSERT INTO \"batch_job_execution\" (\"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\")\n VALUES ($1, $2, $3, NULL, NULL, $4, $5, $6)\n RETURNING \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"`,\n [exec.id, exec.job_instance_id, exec.status, exec.exit_code, exec.exit_message, exec.params],\n ) as JobExecutionRow[];\n return mapJobExecution(rows[0]!);\n }\n\n async createExecutionAtomic(\n name: string,\n jobKey: string,\n params: JobParameters,\n ): Promise<JobExecution> {\n return this.dataSource.transaction(async (em) => {\n // 1. Idempotent INSERT.\n const instId = randomUUID();\n await em.query(\n `INSERT INTO \"batch_job_instance\" (\"id\", \"job_name\", \"job_key\", \"created_at\")\n VALUES ($1, $2, $3, NOW())\n ON CONFLICT (\"job_name\", \"job_key\") DO NOTHING`,\n [instId, name, jobKey],\n );\n\n // 2. Lock the instance row.\n const isSqlite = this.dataSource.options.type === 'better-sqlite3';\n let instanceId: string;\n if (isSqlite) {\n const rows = await em.query(\n `SELECT \"id\" FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n LIMIT 1`,\n [name, jobKey],\n ) as Array<{ id: string }>;\n if (rows.length === 0) {\n throw new JobExecutionAlreadyRunningError(name);\n }\n instanceId = rows[0]!.id;\n } else {\n const rows = await em.query(\n `SELECT \"id\" FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n FOR UPDATE SKIP LOCKED`,\n [name, jobKey],\n ) as Array<{ id: string }>;\n if (rows.length === 0) {\n throw new JobExecutionAlreadyRunningError(name);\n }\n instanceId = rows[0]!.id;\n }\n\n // 3. Under the lock, verify no running execution.\n const running = await em.query(\n `SELECT \"id\" FROM \"batch_job_execution\"\n WHERE \"job_instance_id\" = $1 AND \"status\" IN ($2, $3)\n LIMIT 1`,\n [instanceId, JobStatus.STARTING, JobStatus.STARTED],\n ) as Array<{ id: string }>;\n if (running.length > 0) {\n throw new JobExecutionAlreadyRunningError(running[0]!.id);\n }\n\n // 4. Create the new execution row.\n const execId = randomUUID();\n const inserted = await em.query(\n `INSERT INTO \"batch_job_execution\" (\"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\")\n VALUES ($1, $2, $3, NULL, NULL, '', '', $4)\n RETURNING \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"`,\n [execId, instanceId, JobStatus.STARTING, serializeContext(deepClone(params))],\n ) as JobExecutionRow[];\n return mapJobExecution(inserted[0]!);\n });\n }\n\n async updateJobExecution(executionId: string, patch: JobExecutionPatch): Promise<void> {\n const sets: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (patch.status !== undefined) { sets.push(`\"status\" = $${i++}`); values.push(patch.status); }\n if (patch.startTime !== undefined) { sets.push(`\"start_time\" = $${i++}`); values.push(patch.startTime); }\n if (patch.endTime !== undefined) { sets.push(`\"end_time\" = $${i++}`); values.push(patch.endTime); }\n if (patch.exitCode !== undefined) { sets.push(`\"exit_code\" = $${i++}`); values.push(patch.exitCode); }\n if (patch.exitMessage !== undefined) { sets.push(`\"exit_message\" = $${i++}`); values.push(patch.exitMessage); }\n if (sets.length === 0) return;\n values.push(executionId);\n await this.em().query(\n `UPDATE \"batch_job_execution\" SET ${sets.join(', ')} WHERE \"id\" = $${i}`,\n values,\n );\n }\n\n async getJobExecution(executionId: string): Promise<JobExecution | null> {\n const rows = await this.em().query(\n `SELECT \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"\n FROM \"batch_job_execution\" WHERE \"id\" = $1 LIMIT 1`,\n [executionId],\n ) as JobExecutionRow[];\n return rows.length > 0 ? mapJobExecution(rows[0]!) : null;\n }\n\n override async getJobInstance(jobInstanceId: string): Promise<JobInstance | null> {\n const rows = await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n WHERE \"id\" = $1\n LIMIT 1`,\n [jobInstanceId],\n ) as JobInstanceRow[];\n return rows.length > 0 ? mapJobInstance(rows[0]!) : null;\n }\n\n override async findJobInstances(filter: JobInstanceFilter = {}): Promise<JobInstance[]> {\n const where: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (filter.jobName !== undefined) {\n where.push(`\"job_name\" = $${i++}`);\n values.push(filter.jobName);\n }\n if (filter.jobKey !== undefined) {\n where.push(`\"job_key\" = $${i++}`);\n values.push(filter.jobKey);\n }\n const rows = await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY \"created_at\" ASC, \"id\" ASC`,\n values,\n ) as JobInstanceRow[];\n return rows.map(mapJobInstance);\n }\n\n override async findJobExecutions(filter: JobExecutionFilter = {}): Promise<JobExecution[]> {\n const where: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (filter.jobInstanceId !== undefined) {\n where.push(`\"job_instance_id\" = $${i++}`);\n values.push(filter.jobInstanceId);\n }\n if (filter.status !== undefined) {\n const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];\n const placeholders = statuses.map(() => `$${i++}`);\n where.push(`\"status\" IN (${placeholders.join(', ')})`);\n values.push(...statuses);\n }\n if (filter.startedAfter !== undefined) {\n where.push(`\"start_time\" >= $${i++}`);\n values.push(filter.startedAfter);\n }\n if (filter.startedBefore !== undefined) {\n where.push(`\"start_time\" <= $${i++}`);\n values.push(filter.startedBefore);\n }\n const rows = await this.em().query(\n `SELECT \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"\n FROM \"batch_job_execution\"\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY \"start_time\" DESC NULLS LAST, \"id\" DESC`,\n values,\n ) as JobExecutionRow[];\n return rows.map(mapJobExecution);\n }\n\n async getRunningJobExecution(jobInstanceId: string): Promise<JobExecution | null> {\n if (!jobInstanceId) return null;\n const rows = await this.em().query(\n `SELECT \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"\n FROM \"batch_job_execution\"\n WHERE \"job_instance_id\" = $1 AND \"status\" IN ($2, $3)\n ORDER BY \"start_time\" DESC NULLS LAST LIMIT 1`,\n [jobInstanceId, JobStatus.STARTING, JobStatus.STARTED],\n ) as JobExecutionRow[];\n return rows.length > 0 ? mapJobExecution(rows[0]!) : null;\n }\n\n async createStepExecution(\n jobExecutionId: string,\n stepName: string,\n ): Promise<StepExecution> {\n const stepId = randomUUID();\n const rows = await this.em().query(\n `INSERT INTO \"batch_step_execution\" (\"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\")\n VALUES ($1, $2, $3, $4, 0, 0, 0, 0, 0, '', '', NOW())\n RETURNING \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"`,\n [stepId, jobExecutionId, stepName, StepStatus.STARTING],\n ) as StepExecutionRow[];\n return mapStepExecution(rows[0]!);\n }\n\n async updateStepExecution(\n stepExecutionId: string,\n patch: StepExecutionPatch,\n ): Promise<void> {\n const sets: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (patch.status !== undefined) { sets.push(`\"status\" = $${i++}`); values.push(patch.status); }\n if (patch.readCount !== undefined) { sets.push(`\"read_count\" = $${i++}`); values.push(patch.readCount); }\n if (patch.writeCount !== undefined) { sets.push(`\"write_count\" = $${i++}`); values.push(patch.writeCount); }\n if (patch.skipCount !== undefined) { sets.push(`\"skip_count\" = $${i++}`); values.push(patch.skipCount); }\n if (patch.rollbackCount !== undefined) { sets.push(`\"rollback_count\" = $${i++}`); values.push(patch.rollbackCount); }\n if (patch.commitCount !== undefined) { sets.push(`\"commit_count\" = $${i++}`); values.push(patch.commitCount); }\n if (patch.exitCode !== undefined) { sets.push(`\"exit_code\" = $${i++}`); values.push(patch.exitCode); }\n if (patch.exitMessage !== undefined) { sets.push(`\"exit_message\" = $${i++}`); values.push(patch.exitMessage); }\n if (sets.length === 0) return;\n values.push(stepExecutionId);\n await this.em().query(\n `UPDATE \"batch_step_execution\" SET ${sets.join(', ')} WHERE \"id\" = $${i}`,\n values,\n );\n }\n\n async getStepExecution(stepExecutionId: string): Promise<StepExecution | null> {\n const rows = await this.em().query(\n `SELECT \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"\n FROM \"batch_step_execution\" WHERE \"id\" = $1 LIMIT 1`,\n [stepExecutionId],\n ) as StepExecutionRow[];\n return rows.length > 0 ? mapStepExecution(rows[0]!) : null;\n }\n\n override async findStepExecutions(jobExecutionId: string): Promise<StepExecution[]> {\n const rows = await this.em().query(\n `SELECT \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"\n FROM \"batch_step_execution\"\n WHERE \"job_execution_id\" = $1\n ORDER BY \"created_at\" ASC, \"id\" ASC`,\n [jobExecutionId],\n ) as StepExecutionRow[];\n return rows.map(mapStepExecution);\n }\n\n /**\n * Find the most recently created step execution for the given\n * `(jobExecutionId, stepName)` pair, or `null` when none exists.\n * Insertion order is determined by the `created_at` column; the\n * primary key is a v4 UUID which is random, so a `id DESC` order\n * would not correspond to insertion time. The `created_at DESC,\n * id DESC` secondary order keeps the result stable when two rows\n * share the same `CURRENT_TIMESTAMP` resolution.\n */\n async findLatestStepExecution(\n jobExecutionId: string,\n stepName: string,\n ): Promise<StepExecution | null> {\n const rows = await this.em().query(\n `SELECT \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"\n FROM \"batch_step_execution\"\n WHERE \"job_execution_id\" = $1 AND \"step_name\" = $2\n ORDER BY \"created_at\" DESC, \"id\" DESC\n LIMIT 1`,\n [jobExecutionId, stepName],\n ) as StepExecutionRow[];\n return rows.length > 0 ? mapStepExecution(rows[0]!) : null;\n }\n\n async getExecutionContext(scope: ExecutionScope): Promise<ExecutionContext> {\n const key = scopeKey(scope);\n if (key.startsWith('job::')) {\n const rows = await this.em().query(\n `SELECT \"data\", \"version\" FROM \"batch_job_execution_context\" WHERE \"job_execution_id\" = $1 LIMIT 1`,\n [key.slice(5)],\n ) as ContextRow[];\n if (rows.length > 0) {\n return {\n data: rows[0]!.data.length > 0 ? deserializeContext(rows[0]!.data) : null,\n version: rows[0]!.version,\n };\n }\n } else {\n const rows = await this.em().query(\n `SELECT \"data\", \"version\" FROM \"batch_step_execution_context\" WHERE \"step_execution_id\" = $1 LIMIT 1`,\n [key.slice(6)],\n ) as ContextRow[];\n if (rows.length > 0) {\n return {\n data: rows[0]!.data.length > 0 ? deserializeContext(rows[0]!.data) : null,\n version: rows[0]!.version,\n };\n }\n }\n return { data: null, version: 0 };\n }\n\n async saveExecutionContext(\n scope: ExecutionScope,\n ctx: ExecutionContext,\n version?: number,\n ): Promise<void> {\n assertJsonSerializable(ctx.data);\n const key = scopeKey(scope);\n const serialized = serializeContext(deepClone(ctx.data));\n if (key.startsWith('job::')) {\n const jobExecutionId = key.slice(5);\n const existing = await this.em().query(\n `SELECT \"version\" FROM \"batch_job_execution_context\" WHERE \"job_execution_id\" = $1 LIMIT 1`,\n [jobExecutionId],\n ) as ContextRow[];\n const nextVersion = version !== undefined ? version : (existing.length > 0 ? existing[0]!.version + 1 : 0);\n if (existing.length > 0) {\n await this.em().query(\n `UPDATE \"batch_job_execution_context\" SET \"data\" = $1, \"version\" = $2 WHERE \"job_execution_id\" = $3`,\n [serialized, nextVersion, jobExecutionId],\n );\n } else {\n await this.em().query(\n `INSERT INTO \"batch_job_execution_context\" (\"job_execution_id\", \"data\", \"version\") VALUES ($1, $2, $3)`,\n [jobExecutionId, serialized, nextVersion],\n );\n }\n } else {\n const stepExecutionId = key.slice(6);\n const existing = await this.em().query(\n `SELECT \"version\" FROM \"batch_step_execution_context\" WHERE \"step_execution_id\" = $1 LIMIT 1`,\n [stepExecutionId],\n ) as ContextRow[];\n const nextVersion = version !== undefined ? version : (existing.length > 0 ? existing[0]!.version + 1 : 0);\n if (existing.length > 0) {\n await this.em().query(\n `UPDATE \"batch_step_execution_context\" SET \"data\" = $1, \"version\" = $2 WHERE \"step_execution_id\" = $3`,\n [serialized, nextVersion, stepExecutionId],\n );\n } else {\n await this.em().query(\n `INSERT INTO \"batch_step_execution_context\" (\"step_execution_id\", \"data\", \"version\") VALUES ($1, $2, $3)`,\n [stepExecutionId, serialized, nextVersion],\n );\n }\n }\n }\n}\n"],"names":["TypeOrmJobRepository","scopeKey","scope","jobExecutionId","stepExecutionId","deepClone","value","Date","getTime","Array","isArray","map","v","out","k","Object","keys","mapJobInstance","r","id","jobName","job_name","jobKey","job_key","createdAt","created_at","mapJobExecution","params","length","deserializeContext","jobInstanceId","job_instance_id","status","startTime","start_time","endTime","end_time","exitCode","exit_code","exitMessage","exit_message","mapStepExecution","job_execution_id","stepName","step_name","readCount","read_count","writeCount","write_count","skipCount","skip_count","rollbackCount","rollback_count","commitCount","commit_count","JobRepository","dataSource","em","manager","getOrCreateJobInstance","name","existing","query","randomUUID","inserted","winner","Error","createJobExecution","exec","JobStatus","STARTING","serializeContext","rows","createExecutionAtomic","transaction","instId","isSqlite","options","type","instanceId","JobExecutionAlreadyRunningError","running","STARTED","execId","updateJobExecution","executionId","patch","sets","values","i","undefined","push","join","getJobExecution","getJobInstance","findJobInstances","filter","where","findJobExecutions","statuses","placeholders","startedAfter","startedBefore","getRunningJobExecution","createStepExecution","stepId","StepStatus","updateStepExecution","getStepExecution","findStepExecutions","findLatestStepExecution","getExecutionContext","key","startsWith","slice","data","version","saveExecutionContext","ctx","assertJsonSerializable","serialized","nextVersion"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/repository/typeorm-job-repository.ts"],"sourcesContent":["import { Inject, Injectable } from '@nestjs/common';\nimport { randomUUID } from 'node:crypto';\nimport { DataSource, EntityManager, In } from 'typeorm';\nimport {\n JobRepository,\n JobExecutionAlreadyRunningError,\n assertJsonSerializable,\n serializeContext,\n deserializeContext,\n JobStatus,\n StepStatus,\n} from '@nest-batch/core';\nimport type {\n JobInstance,\n JobExecution,\n JobExecutionPatch,\n JobParameters,\n StepExecution,\n StepExecutionPatch,\n ExecutionContext,\n ExecutionScope,\n JobInstanceFilter,\n JobExecutionFilter,\n} from '@nest-batch/core';\nimport { TypeOrmDriverProvider } from '../typeorm.driver-provider';\n\nfunction scopeKey(scope: ExecutionScope): string {\n if ('jobExecutionId' in scope) return `job::${scope.jobExecutionId}`;\n return `step::${scope.stepExecutionId}`;\n}\n\nfunction deepClone<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value;\n if (value instanceof Date) return new Date(value.getTime()) as unknown as T;\n if (Array.isArray(value)) return value.map((v) => deepClone(v)) as unknown as T;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>)) {\n out[k] = deepClone((value as Record<string, unknown>)[k]);\n }\n return out as T;\n}\n\ninterface JobInstanceRow {\n id: string;\n job_name: string;\n job_key: string;\n created_at: string | Date;\n}\n\ninterface JobExecutionRow {\n id: string;\n job_instance_id: string;\n status: string;\n start_time: string | Date | null;\n end_time: string | Date | null;\n exit_code: string;\n exit_message: string;\n params: string;\n}\n\ninterface StepExecutionRow {\n id: string;\n job_execution_id: string;\n step_name: string;\n status: string;\n read_count: number;\n write_count: number;\n skip_count: number;\n rollback_count: number;\n commit_count: number;\n exit_code: string;\n exit_message: string;\n created_at: string | Date;\n}\n\ninterface ContextRow {\n data: string;\n version: number;\n}\n\nfunction mapJobInstance(r: JobInstanceRow): JobInstance {\n return {\n id: r.id,\n jobName: r.job_name,\n jobKey: r.job_key,\n createdAt: r.created_at instanceof Date ? r.created_at : new Date(r.created_at),\n };\n}\n\nfunction mapJobExecution(r: JobExecutionRow): JobExecution {\n let params: JobParameters = {};\n if (r.params && r.params.length > 0) {\n try {\n params = deserializeContext<JobParameters>(r.params);\n } catch {\n params = {};\n }\n }\n return {\n id: r.id,\n jobInstanceId: r.job_instance_id,\n status: r.status as JobStatus,\n startTime: r.start_time\n ? r.start_time instanceof Date\n ? r.start_time\n : new Date(r.start_time)\n : null,\n endTime: r.end_time ? (r.end_time instanceof Date ? r.end_time : new Date(r.end_time)) : null,\n exitCode: r.exit_code,\n exitMessage: r.exit_message,\n params,\n };\n}\n\nfunction mapStepExecution(r: StepExecutionRow): StepExecution {\n return {\n id: r.id,\n jobExecutionId: r.job_execution_id,\n stepName: r.step_name,\n status: r.status as StepStatus,\n readCount: r.read_count,\n writeCount: r.write_count,\n skipCount: r.skip_count,\n rollbackCount: r.rollback_count,\n commitCount: r.commit_count,\n startTime: null,\n endTime: null,\n exitCode: r.exit_code,\n exitMessage: r.exit_message,\n };\n}\n\n/**\n * TypeORM 1.0.0-backed `JobRepository`.\n *\n * The package is driver-agnostic: the actual `DataSource` is\n * provided by the `@nest-batch/postgresql` (or future\n * `@nest-batch/mysql`) driver sibling via the `TypeOrmDriverProvider`\n * token. The repository itself uses raw SQL via `EntityManager.query`\n * against the table contract represented by this package's exported\n * TypeORM entities. The consuming app owns the runnable migration.\n *\n * The contract guarantees:\n * - `getOrCreateJobInstance` is race-safe via the (jobName, jobKey)\n * unique index.\n * - `createExecutionAtomic` runs inside a single transaction that\n * (a) idempotently upserts the instance row, (b) acquires a row\n * lock with `SELECT ... FOR UPDATE SKIP LOCKED` (PostgreSQL) or\n * a plain select (SQLite test driver), and (c) rejects with\n * `JobExecutionAlreadyRunningError` if a STARTING/STARTED\n * execution already exists.\n * - `saveExecutionContext` deep-clones the data and auto-increments\n * the version counter when `version` is omitted.\n * - `findLatestStepExecution` orders by `created_at` descending.\n */\n@Injectable()\nexport class TypeOrmJobRepository extends JobRepository {\n constructor(@Inject(TypeOrmDriverProvider) private readonly dataSource: DataSource) {\n super();\n }\n\n private em(): EntityManager {\n return this.dataSource.manager;\n }\n\n async getOrCreateJobInstance(name: string, jobKey: string): Promise<JobInstance> {\n const existing = (await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n LIMIT 1`,\n [name, jobKey],\n )) as JobInstanceRow[];\n if (existing.length > 0) return mapJobInstance(existing[0]!);\n\n const id = randomUUID();\n try {\n const inserted = (await this.em().query(\n `INSERT INTO \"batch_job_instance\" (\"id\", \"job_name\", \"job_key\", \"created_at\")\n VALUES ($1, $2, $3, NOW())\n ON CONFLICT (\"job_name\", \"job_key\") DO NOTHING\n RETURNING \"id\", \"job_name\", \"job_key\", \"created_at\"`,\n [id, name, jobKey],\n )) as JobInstanceRow[];\n if (inserted.length > 0) return mapJobInstance(inserted[0]!);\n } catch {\n // Fall through to read-back.\n }\n const winner = (await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n LIMIT 1`,\n [name, jobKey],\n )) as JobInstanceRow[];\n if (winner.length === 0) {\n throw new Error(\n `Failed to upsert JobInstance (${name}, ${jobKey}) and could not read it back`,\n );\n }\n return mapJobInstance(winner[0]!);\n }\n\n async createJobExecution(jobInstanceId: string, params: JobParameters): Promise<JobExecution> {\n const exec = {\n id: randomUUID(),\n job_instance_id: jobInstanceId,\n status: JobStatus.STARTING,\n start_time: null as Date | null,\n end_time: null as Date | null,\n exit_code: '',\n exit_message: '',\n params: serializeContext(deepClone(params)),\n };\n const rows = (await this.em().query(\n `INSERT INTO \"batch_job_execution\" (\"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\")\n VALUES ($1, $2, $3, NULL, NULL, $4, $5, $6)\n RETURNING \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"`,\n [exec.id, exec.job_instance_id, exec.status, exec.exit_code, exec.exit_message, exec.params],\n )) as JobExecutionRow[];\n return mapJobExecution(rows[0]!);\n }\n\n async createExecutionAtomic(\n name: string,\n jobKey: string,\n params: JobParameters,\n ): Promise<JobExecution> {\n return this.dataSource.transaction(async (em) => {\n // 1. Idempotent INSERT.\n const instId = randomUUID();\n await em.query(\n `INSERT INTO \"batch_job_instance\" (\"id\", \"job_name\", \"job_key\", \"created_at\")\n VALUES ($1, $2, $3, NOW())\n ON CONFLICT (\"job_name\", \"job_key\") DO NOTHING`,\n [instId, name, jobKey],\n );\n\n // 2. Lock the instance row.\n const isSqlite = this.dataSource.options.type === 'better-sqlite3';\n let instanceId: string;\n if (isSqlite) {\n const rows = (await em.query(\n `SELECT \"id\" FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n LIMIT 1`,\n [name, jobKey],\n )) as Array<{ id: string }>;\n if (rows.length === 0) {\n throw new JobExecutionAlreadyRunningError(name);\n }\n instanceId = rows[0]!.id;\n } else {\n const rows = (await em.query(\n `SELECT \"id\" FROM \"batch_job_instance\"\n WHERE \"job_name\" = $1 AND \"job_key\" = $2\n FOR UPDATE SKIP LOCKED`,\n [name, jobKey],\n )) as Array<{ id: string }>;\n if (rows.length === 0) {\n throw new JobExecutionAlreadyRunningError(name);\n }\n instanceId = rows[0]!.id;\n }\n\n // 3. Under the lock, verify no running execution.\n const running = (await em.query(\n `SELECT \"id\" FROM \"batch_job_execution\"\n WHERE \"job_instance_id\" = $1 AND \"status\" IN ($2, $3)\n LIMIT 1`,\n [instanceId, JobStatus.STARTING, JobStatus.STARTED],\n )) as Array<{ id: string }>;\n if (running.length > 0) {\n throw new JobExecutionAlreadyRunningError(running[0]!.id);\n }\n\n // 4. Create the new execution row.\n const execId = randomUUID();\n const inserted = (await em.query(\n `INSERT INTO \"batch_job_execution\" (\"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\")\n VALUES ($1, $2, $3, NULL, NULL, '', '', $4)\n RETURNING \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"`,\n [execId, instanceId, JobStatus.STARTING, serializeContext(deepClone(params))],\n )) as JobExecutionRow[];\n return mapJobExecution(inserted[0]!);\n });\n }\n\n async updateJobExecution(executionId: string, patch: JobExecutionPatch): Promise<void> {\n const sets: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (patch.status !== undefined) {\n sets.push(`\"status\" = $${i++}`);\n values.push(patch.status);\n }\n if (patch.startTime !== undefined) {\n sets.push(`\"start_time\" = $${i++}`);\n values.push(patch.startTime);\n }\n if (patch.endTime !== undefined) {\n sets.push(`\"end_time\" = $${i++}`);\n values.push(patch.endTime);\n }\n if (patch.exitCode !== undefined) {\n sets.push(`\"exit_code\" = $${i++}`);\n values.push(patch.exitCode);\n }\n if (patch.exitMessage !== undefined) {\n sets.push(`\"exit_message\" = $${i++}`);\n values.push(patch.exitMessage);\n }\n if (sets.length === 0) return;\n values.push(executionId);\n await this.em().query(\n `UPDATE \"batch_job_execution\" SET ${sets.join(', ')} WHERE \"id\" = $${i}`,\n values,\n );\n }\n\n async getJobExecution(executionId: string): Promise<JobExecution | null> {\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"\n FROM \"batch_job_execution\" WHERE \"id\" = $1 LIMIT 1`,\n [executionId],\n )) as JobExecutionRow[];\n return rows.length > 0 ? mapJobExecution(rows[0]!) : null;\n }\n\n override async getJobInstance(jobInstanceId: string): Promise<JobInstance | null> {\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n WHERE \"id\" = $1\n LIMIT 1`,\n [jobInstanceId],\n )) as JobInstanceRow[];\n return rows.length > 0 ? mapJobInstance(rows[0]!) : null;\n }\n\n override async findJobInstances(filter: JobInstanceFilter = {}): Promise<JobInstance[]> {\n const where: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (filter.jobName !== undefined) {\n where.push(`\"job_name\" = $${i++}`);\n values.push(filter.jobName);\n }\n if (filter.jobKey !== undefined) {\n where.push(`\"job_key\" = $${i++}`);\n values.push(filter.jobKey);\n }\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_name\", \"job_key\", \"created_at\"\n FROM \"batch_job_instance\"\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY \"created_at\" ASC, \"id\" ASC`,\n values,\n )) as JobInstanceRow[];\n return rows.map(mapJobInstance);\n }\n\n override async findJobExecutions(filter: JobExecutionFilter = {}): Promise<JobExecution[]> {\n const where: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (filter.jobInstanceId !== undefined) {\n where.push(`\"job_instance_id\" = $${i++}`);\n values.push(filter.jobInstanceId);\n }\n if (filter.status !== undefined) {\n const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];\n const placeholders = statuses.map(() => `$${i++}`);\n where.push(`\"status\" IN (${placeholders.join(', ')})`);\n values.push(...statuses);\n }\n if (filter.startedAfter !== undefined) {\n where.push(`\"start_time\" >= $${i++}`);\n values.push(filter.startedAfter);\n }\n if (filter.startedBefore !== undefined) {\n where.push(`\"start_time\" <= $${i++}`);\n values.push(filter.startedBefore);\n }\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"\n FROM \"batch_job_execution\"\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY \"start_time\" DESC NULLS LAST, \"id\" DESC`,\n values,\n )) as JobExecutionRow[];\n return rows.map(mapJobExecution);\n }\n\n async getRunningJobExecution(jobInstanceId: string): Promise<JobExecution | null> {\n if (!jobInstanceId) return null;\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_instance_id\", \"status\", \"start_time\", \"end_time\", \"exit_code\", \"exit_message\", \"params\"\n FROM \"batch_job_execution\"\n WHERE \"job_instance_id\" = $1 AND \"status\" IN ($2, $3)\n ORDER BY \"start_time\" DESC NULLS LAST LIMIT 1`,\n [jobInstanceId, JobStatus.STARTING, JobStatus.STARTED],\n )) as JobExecutionRow[];\n return rows.length > 0 ? mapJobExecution(rows[0]!) : null;\n }\n\n async createStepExecution(jobExecutionId: string, stepName: string): Promise<StepExecution> {\n const stepId = randomUUID();\n const rows = (await this.em().query(\n `INSERT INTO \"batch_step_execution\" (\"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\")\n VALUES ($1, $2, $3, $4, 0, 0, 0, 0, 0, '', '', NOW())\n RETURNING \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"`,\n [stepId, jobExecutionId, stepName, StepStatus.STARTING],\n )) as StepExecutionRow[];\n return mapStepExecution(rows[0]!);\n }\n\n async updateStepExecution(stepExecutionId: string, patch: StepExecutionPatch): Promise<void> {\n const sets: string[] = [];\n const values: unknown[] = [];\n let i = 1;\n if (patch.status !== undefined) {\n sets.push(`\"status\" = $${i++}`);\n values.push(patch.status);\n }\n if (patch.readCount !== undefined) {\n sets.push(`\"read_count\" = $${i++}`);\n values.push(patch.readCount);\n }\n if (patch.writeCount !== undefined) {\n sets.push(`\"write_count\" = $${i++}`);\n values.push(patch.writeCount);\n }\n if (patch.skipCount !== undefined) {\n sets.push(`\"skip_count\" = $${i++}`);\n values.push(patch.skipCount);\n }\n if (patch.rollbackCount !== undefined) {\n sets.push(`\"rollback_count\" = $${i++}`);\n values.push(patch.rollbackCount);\n }\n if (patch.commitCount !== undefined) {\n sets.push(`\"commit_count\" = $${i++}`);\n values.push(patch.commitCount);\n }\n if (patch.exitCode !== undefined) {\n sets.push(`\"exit_code\" = $${i++}`);\n values.push(patch.exitCode);\n }\n if (patch.exitMessage !== undefined) {\n sets.push(`\"exit_message\" = $${i++}`);\n values.push(patch.exitMessage);\n }\n if (sets.length === 0) return;\n values.push(stepExecutionId);\n await this.em().query(\n `UPDATE \"batch_step_execution\" SET ${sets.join(', ')} WHERE \"id\" = $${i}`,\n values,\n );\n }\n\n async getStepExecution(stepExecutionId: string): Promise<StepExecution | null> {\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"\n FROM \"batch_step_execution\" WHERE \"id\" = $1 LIMIT 1`,\n [stepExecutionId],\n )) as StepExecutionRow[];\n return rows.length > 0 ? mapStepExecution(rows[0]!) : null;\n }\n\n override async findStepExecutions(jobExecutionId: string): Promise<StepExecution[]> {\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"\n FROM \"batch_step_execution\"\n WHERE \"job_execution_id\" = $1\n ORDER BY \"created_at\" ASC, \"id\" ASC`,\n [jobExecutionId],\n )) as StepExecutionRow[];\n return rows.map(mapStepExecution);\n }\n\n /**\n * Find the most recently created step execution for the given\n * `(jobExecutionId, stepName)` pair, or `null` when none exists.\n * Insertion order is determined by the `created_at` column; the\n * primary key is a v4 UUID which is random, so a `id DESC` order\n * would not correspond to insertion time. The `created_at DESC,\n * id DESC` secondary order keeps the result stable when two rows\n * share the same `CURRENT_TIMESTAMP` resolution.\n */\n async findLatestStepExecution(\n jobExecutionId: string,\n stepName: string,\n ): Promise<StepExecution | null> {\n const rows = (await this.em().query(\n `SELECT \"id\", \"job_execution_id\", \"step_name\", \"status\", \"read_count\", \"write_count\", \"skip_count\", \"rollback_count\", \"commit_count\", \"exit_code\", \"exit_message\", \"created_at\"\n FROM \"batch_step_execution\"\n WHERE \"job_execution_id\" = $1 AND \"step_name\" = $2\n ORDER BY \"created_at\" DESC, \"id\" DESC\n LIMIT 1`,\n [jobExecutionId, stepName],\n )) as StepExecutionRow[];\n return rows.length > 0 ? mapStepExecution(rows[0]!) : null;\n }\n\n async getExecutionContext(scope: ExecutionScope): Promise<ExecutionContext> {\n const key = scopeKey(scope);\n if (key.startsWith('job::')) {\n const rows = (await this.em().query(\n `SELECT \"data\", \"version\" FROM \"batch_job_execution_context\" WHERE \"job_execution_id\" = $1 LIMIT 1`,\n [key.slice(5)],\n )) as ContextRow[];\n if (rows.length > 0) {\n return {\n data: rows[0]!.data.length > 0 ? deserializeContext(rows[0]!.data) : null,\n version: rows[0]!.version,\n };\n }\n } else {\n const rows = (await this.em().query(\n `SELECT \"data\", \"version\" FROM \"batch_step_execution_context\" WHERE \"step_execution_id\" = $1 LIMIT 1`,\n [key.slice(6)],\n )) as ContextRow[];\n if (rows.length > 0) {\n return {\n data: rows[0]!.data.length > 0 ? deserializeContext(rows[0]!.data) : null,\n version: rows[0]!.version,\n };\n }\n }\n return { data: null, version: 0 };\n }\n\n async saveExecutionContext(\n scope: ExecutionScope,\n ctx: ExecutionContext,\n version?: number,\n ): Promise<void> {\n assertJsonSerializable(ctx.data);\n const key = scopeKey(scope);\n const serialized = serializeContext(deepClone(ctx.data));\n if (key.startsWith('job::')) {\n const jobExecutionId = key.slice(5);\n const existing = (await this.em().query(\n `SELECT \"version\" FROM \"batch_job_execution_context\" WHERE \"job_execution_id\" = $1 LIMIT 1`,\n [jobExecutionId],\n )) as ContextRow[];\n const nextVersion =\n version !== undefined ? version : existing.length > 0 ? existing[0]!.version + 1 : 0;\n if (existing.length > 0) {\n await this.em().query(\n `UPDATE \"batch_job_execution_context\" SET \"data\" = $1, \"version\" = $2 WHERE \"job_execution_id\" = $3`,\n [serialized, nextVersion, jobExecutionId],\n );\n } else {\n await this.em().query(\n `INSERT INTO \"batch_job_execution_context\" (\"job_execution_id\", \"data\", \"version\") VALUES ($1, $2, $3)`,\n [jobExecutionId, serialized, nextVersion],\n );\n }\n } else {\n const stepExecutionId = key.slice(6);\n const existing = (await this.em().query(\n `SELECT \"version\" FROM \"batch_step_execution_context\" WHERE \"step_execution_id\" = $1 LIMIT 1`,\n [stepExecutionId],\n )) as ContextRow[];\n const nextVersion =\n version !== undefined ? version : existing.length > 0 ? existing[0]!.version + 1 : 0;\n if (existing.length > 0) {\n await this.em().query(\n `UPDATE \"batch_step_execution_context\" SET \"data\" = $1, \"version\" = $2 WHERE \"step_execution_id\" = $3`,\n [serialized, nextVersion, stepExecutionId],\n );\n } else {\n await this.em().query(\n `INSERT INTO \"batch_step_execution_context\" (\"step_execution_id\", \"data\", \"version\") VALUES ($1, $2, $3)`,\n [stepExecutionId, serialized, nextVersion],\n );\n }\n }\n }\n}\n"],"names":["TypeOrmJobRepository","scopeKey","scope","jobExecutionId","stepExecutionId","deepClone","value","Date","getTime","Array","isArray","map","v","out","k","Object","keys","mapJobInstance","r","id","jobName","job_name","jobKey","job_key","createdAt","created_at","mapJobExecution","params","length","deserializeContext","jobInstanceId","job_instance_id","status","startTime","start_time","endTime","end_time","exitCode","exit_code","exitMessage","exit_message","mapStepExecution","job_execution_id","stepName","step_name","readCount","read_count","writeCount","write_count","skipCount","skip_count","rollbackCount","rollback_count","commitCount","commit_count","JobRepository","dataSource","em","manager","getOrCreateJobInstance","name","existing","query","randomUUID","inserted","winner","Error","createJobExecution","exec","JobStatus","STARTING","serializeContext","rows","createExecutionAtomic","transaction","instId","isSqlite","options","type","instanceId","JobExecutionAlreadyRunningError","running","STARTED","execId","updateJobExecution","executionId","patch","sets","values","i","undefined","push","join","getJobExecution","getJobInstance","findJobInstances","filter","where","findJobExecutions","statuses","placeholders","startedAfter","startedBefore","getRunningJobExecution","createStepExecution","stepId","StepStatus","updateStepExecution","getStepExecution","findStepExecutions","findLatestStepExecution","getExecutionContext","key","startsWith","slice","data","version","saveExecutionContext","ctx","assertJsonSerializable","serialized","nextVersion"],"mappings":";;;;+BA4JaA;;;eAAAA;;;wBA5JsB;4BACR;yBACmB;sBASvC;uCAa+B;;;;;;;;;;;;;;;AAEtC,SAASC,SAASC,KAAqB;IACrC,IAAI,oBAAoBA,OAAO,OAAO,CAAC,KAAK,EAAEA,MAAMC,cAAc,EAAE;IACpE,OAAO,CAAC,MAAM,EAAED,MAAME,eAAe,EAAE;AACzC;AAEA,SAASC,UAAaC,KAAQ;IAC5B,IAAIA,UAAU,QAAQ,OAAOA,UAAU,UAAU,OAAOA;IACxD,IAAIA,iBAAiBC,MAAM,OAAO,IAAIA,KAAKD,MAAME,OAAO;IACxD,IAAIC,MAAMC,OAAO,CAACJ,QAAQ,OAAOA,MAAMK,GAAG,CAAC,CAACC,IAAMP,UAAUO;IAC5D,MAAMC,MAA+B,CAAC;IACtC,KAAK,MAAMC,KAAKC,OAAOC,IAAI,CAACV,OAAmC;QAC7DO,GAAG,CAACC,EAAE,GAAGT,UAAU,AAACC,KAAiC,CAACQ,EAAE;IAC1D;IACA,OAAOD;AACT;AAwCA,SAASI,eAAeC,CAAiB;IACvC,OAAO;QACLC,IAAID,EAAEC,EAAE;QACRC,SAASF,EAAEG,QAAQ;QACnBC,QAAQJ,EAAEK,OAAO;QACjBC,WAAWN,EAAEO,UAAU,YAAYlB,OAAOW,EAAEO,UAAU,GAAG,IAAIlB,KAAKW,EAAEO,UAAU;IAChF;AACF;AAEA,SAASC,gBAAgBR,CAAkB;IACzC,IAAIS,SAAwB,CAAC;IAC7B,IAAIT,EAAES,MAAM,IAAIT,EAAES,MAAM,CAACC,MAAM,GAAG,GAAG;QACnC,IAAI;YACFD,SAASE,IAAAA,wBAAkB,EAAgBX,EAAES,MAAM;QACrD,EAAE,OAAM;YACNA,SAAS,CAAC;QACZ;IACF;IACA,OAAO;QACLR,IAAID,EAAEC,EAAE;QACRW,eAAeZ,EAAEa,eAAe;QAChCC,QAAQd,EAAEc,MAAM;QAChBC,WAAWf,EAAEgB,UAAU,GACnBhB,EAAEgB,UAAU,YAAY3B,OACtBW,EAAEgB,UAAU,GACZ,IAAI3B,KAAKW,EAAEgB,UAAU,IACvB;QACJC,SAASjB,EAAEkB,QAAQ,GAAIlB,EAAEkB,QAAQ,YAAY7B,OAAOW,EAAEkB,QAAQ,GAAG,IAAI7B,KAAKW,EAAEkB,QAAQ,IAAK;QACzFC,UAAUnB,EAAEoB,SAAS;QACrBC,aAAarB,EAAEsB,YAAY;QAC3Bb;IACF;AACF;AAEA,SAASc,iBAAiBvB,CAAmB;IAC3C,OAAO;QACLC,IAAID,EAAEC,EAAE;QACRhB,gBAAgBe,EAAEwB,gBAAgB;QAClCC,UAAUzB,EAAE0B,SAAS;QACrBZ,QAAQd,EAAEc,MAAM;QAChBa,WAAW3B,EAAE4B,UAAU;QACvBC,YAAY7B,EAAE8B,WAAW;QACzBC,WAAW/B,EAAEgC,UAAU;QACvBC,eAAejC,EAAEkC,cAAc;QAC/BC,aAAanC,EAAEoC,YAAY;QAC3BrB,WAAW;QACXE,SAAS;QACTE,UAAUnB,EAAEoB,SAAS;QACrBC,aAAarB,EAAEsB,YAAY;IAC7B;AACF;AA0BO,IAAA,AAAMxC,uBAAN,MAAMA,6BAA6BuD,mBAAa;;IACrD,YAAY,AAAgDC,UAAsB,CAAE;QAClF,KAAK,SADqDA,aAAAA;IAE5D;IAEQC,KAAoB;QAC1B,OAAO,IAAI,CAACD,UAAU,CAACE,OAAO;IAChC;IAEA,MAAMC,uBAAuBC,IAAY,EAAEtC,MAAc,EAAwB;QAC/E,MAAMuC,WAAY,MAAM,IAAI,CAACJ,EAAE,GAAGK,KAAK,CACrC,CAAC;;;cAGO,CAAC,EACT;YAACF;YAAMtC;SAAO;QAEhB,IAAIuC,SAASjC,MAAM,GAAG,GAAG,OAAOX,eAAe4C,QAAQ,CAAC,EAAE;QAE1D,MAAM1C,KAAK4C,IAAAA,sBAAU;QACrB,IAAI;YACF,MAAMC,WAAY,MAAM,IAAI,CAACP,EAAE,GAAGK,KAAK,CACrC,CAAC;;;4DAGmD,CAAC,EACrD;gBAAC3C;gBAAIyC;gBAAMtC;aAAO;YAEpB,IAAI0C,SAASpC,MAAM,GAAG,GAAG,OAAOX,eAAe+C,QAAQ,CAAC,EAAE;QAC5D,EAAE,OAAM;QACN,6BAA6B;QAC/B;QACA,MAAMC,SAAU,MAAM,IAAI,CAACR,EAAE,GAAGK,KAAK,CACnC,CAAC;;;cAGO,CAAC,EACT;YAACF;YAAMtC;SAAO;QAEhB,IAAI2C,OAAOrC,MAAM,KAAK,GAAG;YACvB,MAAM,IAAIsC,MACR,CAAC,8BAA8B,EAAEN,KAAK,EAAE,EAAEtC,OAAO,4BAA4B,CAAC;QAElF;QACA,OAAOL,eAAegD,MAAM,CAAC,EAAE;IACjC;IAEA,MAAME,mBAAmBrC,aAAqB,EAAEH,MAAqB,EAAyB;QAC5F,MAAMyC,OAAO;YACXjD,IAAI4C,IAAAA,sBAAU;YACdhC,iBAAiBD;YACjBE,QAAQqC,eAAS,CAACC,QAAQ;YAC1BpC,YAAY;YACZE,UAAU;YACVE,WAAW;YACXE,cAAc;YACdb,QAAQ4C,IAAAA,sBAAgB,EAAClE,UAAUsB;QACrC;QACA,MAAM6C,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;mHAE4G,CAAC,EAC9G;YAACM,KAAKjD,EAAE;YAAEiD,KAAKrC,eAAe;YAAEqC,KAAKpC,MAAM;YAAEoC,KAAK9B,SAAS;YAAE8B,KAAK5B,YAAY;YAAE4B,KAAKzC,MAAM;SAAC;QAE9F,OAAOD,gBAAgB8C,IAAI,CAAC,EAAE;IAChC;IAEA,MAAMC,sBACJb,IAAY,EACZtC,MAAc,EACdK,MAAqB,EACE;QACvB,OAAO,IAAI,CAAC6B,UAAU,CAACkB,WAAW,CAAC,OAAOjB;YACxC,wBAAwB;YACxB,MAAMkB,SAASZ,IAAAA,sBAAU;YACzB,MAAMN,GAAGK,KAAK,CACZ,CAAC;;uDAE8C,CAAC,EAChD;gBAACa;gBAAQf;gBAAMtC;aAAO;YAGxB,4BAA4B;YAC5B,MAAMsD,WAAW,IAAI,CAACpB,UAAU,CAACqB,OAAO,CAACC,IAAI,KAAK;YAClD,IAAIC;YACJ,IAAIH,UAAU;gBACZ,MAAMJ,OAAQ,MAAMf,GAAGK,KAAK,CAC1B,CAAC;;kBAEO,CAAC,EACT;oBAACF;oBAAMtC;iBAAO;gBAEhB,IAAIkD,KAAK5C,MAAM,KAAK,GAAG;oBACrB,MAAM,IAAIoD,qCAA+B,CAACpB;gBAC5C;gBACAmB,aAAaP,IAAI,CAAC,EAAE,CAAErD,EAAE;YAC1B,OAAO;gBACL,MAAMqD,OAAQ,MAAMf,GAAGK,KAAK,CAC1B,CAAC;;iCAEsB,CAAC,EACxB;oBAACF;oBAAMtC;iBAAO;gBAEhB,IAAIkD,KAAK5C,MAAM,KAAK,GAAG;oBACrB,MAAM,IAAIoD,qCAA+B,CAACpB;gBAC5C;gBACAmB,aAAaP,IAAI,CAAC,EAAE,CAAErD,EAAE;YAC1B;YAEA,kDAAkD;YAClD,MAAM8D,UAAW,MAAMxB,GAAGK,KAAK,CAC7B,CAAC;;gBAEO,CAAC,EACT;gBAACiB;gBAAYV,eAAS,CAACC,QAAQ;gBAAED,eAAS,CAACa,OAAO;aAAC;YAErD,IAAID,QAAQrD,MAAM,GAAG,GAAG;gBACtB,MAAM,IAAIoD,qCAA+B,CAACC,OAAO,CAAC,EAAE,CAAE9D,EAAE;YAC1D;YAEA,mCAAmC;YACnC,MAAMgE,SAASpB,IAAAA,sBAAU;YACzB,MAAMC,WAAY,MAAMP,GAAGK,KAAK,CAC9B,CAAC;;qHAE4G,CAAC,EAC9G;gBAACqB;gBAAQJ;gBAAYV,eAAS,CAACC,QAAQ;gBAAEC,IAAAA,sBAAgB,EAAClE,UAAUsB;aAAS;YAE/E,OAAOD,gBAAgBsC,QAAQ,CAAC,EAAE;QACpC;IACF;IAEA,MAAMoB,mBAAmBC,WAAmB,EAAEC,KAAwB,EAAiB;QACrF,MAAMC,OAAiB,EAAE;QACzB,MAAMC,SAAoB,EAAE;QAC5B,IAAIC,IAAI;QACR,IAAIH,MAAMtD,MAAM,KAAK0D,WAAW;YAC9BH,KAAKI,IAAI,CAAC,CAAC,YAAY,EAAEF,KAAK;YAC9BD,OAAOG,IAAI,CAACL,MAAMtD,MAAM;QAC1B;QACA,IAAIsD,MAAMrD,SAAS,KAAKyD,WAAW;YACjCH,KAAKI,IAAI,CAAC,CAAC,gBAAgB,EAAEF,KAAK;YAClCD,OAAOG,IAAI,CAACL,MAAMrD,SAAS;QAC7B;QACA,IAAIqD,MAAMnD,OAAO,KAAKuD,WAAW;YAC/BH,KAAKI,IAAI,CAAC,CAAC,cAAc,EAAEF,KAAK;YAChCD,OAAOG,IAAI,CAACL,MAAMnD,OAAO;QAC3B;QACA,IAAImD,MAAMjD,QAAQ,KAAKqD,WAAW;YAChCH,KAAKI,IAAI,CAAC,CAAC,eAAe,EAAEF,KAAK;YACjCD,OAAOG,IAAI,CAACL,MAAMjD,QAAQ;QAC5B;QACA,IAAIiD,MAAM/C,WAAW,KAAKmD,WAAW;YACnCH,KAAKI,IAAI,CAAC,CAAC,kBAAkB,EAAEF,KAAK;YACpCD,OAAOG,IAAI,CAACL,MAAM/C,WAAW;QAC/B;QACA,IAAIgD,KAAK3D,MAAM,KAAK,GAAG;QACvB4D,OAAOG,IAAI,CAACN;QACZ,MAAM,IAAI,CAAC5B,EAAE,GAAGK,KAAK,CACnB,CAAC,iCAAiC,EAAEyB,KAAKK,IAAI,CAAC,MAAM,eAAe,EAAEH,GAAG,EACxED;IAEJ;IAEA,MAAMK,gBAAgBR,WAAmB,EAAgC;QACvE,MAAMb,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;yDACkD,CAAC,EACpD;YAACuB;SAAY;QAEf,OAAOb,KAAK5C,MAAM,GAAG,IAAIF,gBAAgB8C,IAAI,CAAC,EAAE,IAAK;IACvD;IAEA,MAAesB,eAAehE,aAAqB,EAA+B;QAChF,MAAM0C,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;;cAGO,CAAC,EACT;YAAChC;SAAc;QAEjB,OAAO0C,KAAK5C,MAAM,GAAG,IAAIX,eAAeuD,IAAI,CAAC,EAAE,IAAK;IACtD;IAEA,MAAeuB,iBAAiBC,SAA4B,CAAC,CAAC,EAA0B;QACtF,MAAMC,QAAkB,EAAE;QAC1B,MAAMT,SAAoB,EAAE;QAC5B,IAAIC,IAAI;QACR,IAAIO,OAAO5E,OAAO,KAAKsE,WAAW;YAChCO,MAAMN,IAAI,CAAC,CAAC,cAAc,EAAEF,KAAK;YACjCD,OAAOG,IAAI,CAACK,OAAO5E,OAAO;QAC5B;QACA,IAAI4E,OAAO1E,MAAM,KAAKoE,WAAW;YAC/BO,MAAMN,IAAI,CAAC,CAAC,aAAa,EAAEF,KAAK;YAChCD,OAAOG,IAAI,CAACK,OAAO1E,MAAM;QAC3B;QACA,MAAMkD,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;OAEA,EAAEmC,MAAMrE,MAAM,GAAG,IAAI,CAAC,MAAM,EAAEqE,MAAML,IAAI,CAAC,UAAU,GAAG,GAAG;0CACtB,CAAC,EACrCJ;QAEF,OAAOhB,KAAK7D,GAAG,CAACM;IAClB;IAEA,MAAeiF,kBAAkBF,SAA6B,CAAC,CAAC,EAA2B;QACzF,MAAMC,QAAkB,EAAE;QAC1B,MAAMT,SAAoB,EAAE;QAC5B,IAAIC,IAAI;QACR,IAAIO,OAAOlE,aAAa,KAAK4D,WAAW;YACtCO,MAAMN,IAAI,CAAC,CAAC,qBAAqB,EAAEF,KAAK;YACxCD,OAAOG,IAAI,CAACK,OAAOlE,aAAa;QAClC;QACA,IAAIkE,OAAOhE,MAAM,KAAK0D,WAAW;YAC/B,MAAMS,WAAW1F,MAAMC,OAAO,CAACsF,OAAOhE,MAAM,IAAIgE,OAAOhE,MAAM,GAAG;gBAACgE,OAAOhE,MAAM;aAAC;YAC/E,MAAMoE,eAAeD,SAASxF,GAAG,CAAC,IAAM,CAAC,CAAC,EAAE8E,KAAK;YACjDQ,MAAMN,IAAI,CAAC,CAAC,aAAa,EAAES,aAAaR,IAAI,CAAC,MAAM,CAAC,CAAC;YACrDJ,OAAOG,IAAI,IAAIQ;QACjB;QACA,IAAIH,OAAOK,YAAY,KAAKX,WAAW;YACrCO,MAAMN,IAAI,CAAC,CAAC,iBAAiB,EAAEF,KAAK;YACpCD,OAAOG,IAAI,CAACK,OAAOK,YAAY;QACjC;QACA,IAAIL,OAAOM,aAAa,KAAKZ,WAAW;YACtCO,MAAMN,IAAI,CAAC,CAAC,iBAAiB,EAAEF,KAAK;YACpCD,OAAOG,IAAI,CAACK,OAAOM,aAAa;QAClC;QACA,MAAM9B,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;OAEA,EAAEmC,MAAMrE,MAAM,GAAG,IAAI,CAAC,MAAM,EAAEqE,MAAML,IAAI,CAAC,UAAU,GAAG,GAAG;uDACT,CAAC,EAClDJ;QAEF,OAAOhB,KAAK7D,GAAG,CAACe;IAClB;IAEA,MAAM6E,uBAAuBzE,aAAqB,EAAgC;QAChF,IAAI,CAACA,eAAe,OAAO;QAC3B,MAAM0C,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;;oDAG6C,CAAC,EAC/C;YAAChC;YAAeuC,eAAS,CAACC,QAAQ;YAAED,eAAS,CAACa,OAAO;SAAC;QAExD,OAAOV,KAAK5C,MAAM,GAAG,IAAIF,gBAAgB8C,IAAI,CAAC,EAAE,IAAK;IACvD;IAEA,MAAMgC,oBAAoBrG,cAAsB,EAAEwC,QAAgB,EAA0B;QAC1F,MAAM8D,SAAS1C,IAAAA,sBAAU;QACzB,MAAMS,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;wLAEiL,CAAC,EACnL;YAAC2C;YAAQtG;YAAgBwC;YAAU+D,gBAAU,CAACpC,QAAQ;SAAC;QAEzD,OAAO7B,iBAAiB+B,IAAI,CAAC,EAAE;IACjC;IAEA,MAAMmC,oBAAoBvG,eAAuB,EAAEkF,KAAyB,EAAiB;QAC3F,MAAMC,OAAiB,EAAE;QACzB,MAAMC,SAAoB,EAAE;QAC5B,IAAIC,IAAI;QACR,IAAIH,MAAMtD,MAAM,KAAK0D,WAAW;YAC9BH,KAAKI,IAAI,CAAC,CAAC,YAAY,EAAEF,KAAK;YAC9BD,OAAOG,IAAI,CAACL,MAAMtD,MAAM;QAC1B;QACA,IAAIsD,MAAMzC,SAAS,KAAK6C,WAAW;YACjCH,KAAKI,IAAI,CAAC,CAAC,gBAAgB,EAAEF,KAAK;YAClCD,OAAOG,IAAI,CAACL,MAAMzC,SAAS;QAC7B;QACA,IAAIyC,MAAMvC,UAAU,KAAK2C,WAAW;YAClCH,KAAKI,IAAI,CAAC,CAAC,iBAAiB,EAAEF,KAAK;YACnCD,OAAOG,IAAI,CAACL,MAAMvC,UAAU;QAC9B;QACA,IAAIuC,MAAMrC,SAAS,KAAKyC,WAAW;YACjCH,KAAKI,IAAI,CAAC,CAAC,gBAAgB,EAAEF,KAAK;YAClCD,OAAOG,IAAI,CAACL,MAAMrC,SAAS;QAC7B;QACA,IAAIqC,MAAMnC,aAAa,KAAKuC,WAAW;YACrCH,KAAKI,IAAI,CAAC,CAAC,oBAAoB,EAAEF,KAAK;YACtCD,OAAOG,IAAI,CAACL,MAAMnC,aAAa;QACjC;QACA,IAAImC,MAAMjC,WAAW,KAAKqC,WAAW;YACnCH,KAAKI,IAAI,CAAC,CAAC,kBAAkB,EAAEF,KAAK;YACpCD,OAAOG,IAAI,CAACL,MAAMjC,WAAW;QAC/B;QACA,IAAIiC,MAAMjD,QAAQ,KAAKqD,WAAW;YAChCH,KAAKI,IAAI,CAAC,CAAC,eAAe,EAAEF,KAAK;YACjCD,OAAOG,IAAI,CAACL,MAAMjD,QAAQ;QAC5B;QACA,IAAIiD,MAAM/C,WAAW,KAAKmD,WAAW;YACnCH,KAAKI,IAAI,CAAC,CAAC,kBAAkB,EAAEF,KAAK;YACpCD,OAAOG,IAAI,CAACL,MAAM/C,WAAW;QAC/B;QACA,IAAIgD,KAAK3D,MAAM,KAAK,GAAG;QACvB4D,OAAOG,IAAI,CAACvF;QACZ,MAAM,IAAI,CAACqD,EAAE,GAAGK,KAAK,CACnB,CAAC,kCAAkC,EAAEyB,KAAKK,IAAI,CAAC,MAAM,eAAe,EAAEH,GAAG,EACzED;IAEJ;IAEA,MAAMoB,iBAAiBxG,eAAuB,EAAiC;QAC7E,MAAMoE,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;0DACmD,CAAC,EACrD;YAAC1D;SAAgB;QAEnB,OAAOoE,KAAK5C,MAAM,GAAG,IAAIa,iBAAiB+B,IAAI,CAAC,EAAE,IAAK;IACxD;IAEA,MAAeqC,mBAAmB1G,cAAsB,EAA4B;QAClF,MAAMqE,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;;0CAGmC,CAAC,EACrC;YAAC3D;SAAe;QAElB,OAAOqE,KAAK7D,GAAG,CAAC8B;IAClB;IAEA;;;;;;;;GAQC,GACD,MAAMqE,wBACJ3G,cAAsB,EACtBwC,QAAgB,EACe;QAC/B,MAAM6B,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC;;;;cAIO,CAAC,EACT;YAAC3D;YAAgBwC;SAAS;QAE5B,OAAO6B,KAAK5C,MAAM,GAAG,IAAIa,iBAAiB+B,IAAI,CAAC,EAAE,IAAK;IACxD;IAEA,MAAMuC,oBAAoB7G,KAAqB,EAA6B;QAC1E,MAAM8G,MAAM/G,SAASC;QACrB,IAAI8G,IAAIC,UAAU,CAAC,UAAU;YAC3B,MAAMzC,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC,iGAAiG,CAAC,EACnG;gBAACkD,IAAIE,KAAK,CAAC;aAAG;YAEhB,IAAI1C,KAAK5C,MAAM,GAAG,GAAG;gBACnB,OAAO;oBACLuF,MAAM3C,IAAI,CAAC,EAAE,CAAE2C,IAAI,CAACvF,MAAM,GAAG,IAAIC,IAAAA,wBAAkB,EAAC2C,IAAI,CAAC,EAAE,CAAE2C,IAAI,IAAI;oBACrEC,SAAS5C,IAAI,CAAC,EAAE,CAAE4C,OAAO;gBAC3B;YACF;QACF,OAAO;YACL,MAAM5C,OAAQ,MAAM,IAAI,CAACf,EAAE,GAAGK,KAAK,CACjC,CAAC,mGAAmG,CAAC,EACrG;gBAACkD,IAAIE,KAAK,CAAC;aAAG;YAEhB,IAAI1C,KAAK5C,MAAM,GAAG,GAAG;gBACnB,OAAO;oBACLuF,MAAM3C,IAAI,CAAC,EAAE,CAAE2C,IAAI,CAACvF,MAAM,GAAG,IAAIC,IAAAA,wBAAkB,EAAC2C,IAAI,CAAC,EAAE,CAAE2C,IAAI,IAAI;oBACrEC,SAAS5C,IAAI,CAAC,EAAE,CAAE4C,OAAO;gBAC3B;YACF;QACF;QACA,OAAO;YAAED,MAAM;YAAMC,SAAS;QAAE;IAClC;IAEA,MAAMC,qBACJnH,KAAqB,EACrBoH,GAAqB,EACrBF,OAAgB,EACD;QACfG,IAAAA,4BAAsB,EAACD,IAAIH,IAAI;QAC/B,MAAMH,MAAM/G,SAASC;QACrB,MAAMsH,aAAajD,IAAAA,sBAAgB,EAAClE,UAAUiH,IAAIH,IAAI;QACtD,IAAIH,IAAIC,UAAU,CAAC,UAAU;YAC3B,MAAM9G,iBAAiB6G,IAAIE,KAAK,CAAC;YACjC,MAAMrD,WAAY,MAAM,IAAI,CAACJ,EAAE,GAAGK,KAAK,CACrC,CAAC,yFAAyF,CAAC,EAC3F;gBAAC3D;aAAe;YAElB,MAAMsH,cACJL,YAAY1B,YAAY0B,UAAUvD,SAASjC,MAAM,GAAG,IAAIiC,QAAQ,CAAC,EAAE,CAAEuD,OAAO,GAAG,IAAI;YACrF,IAAIvD,SAASjC,MAAM,GAAG,GAAG;gBACvB,MAAM,IAAI,CAAC6B,EAAE,GAAGK,KAAK,CACnB,CAAC,kGAAkG,CAAC,EACpG;oBAAC0D;oBAAYC;oBAAatH;iBAAe;YAE7C,OAAO;gBACL,MAAM,IAAI,CAACsD,EAAE,GAAGK,KAAK,CACnB,CAAC,qGAAqG,CAAC,EACvG;oBAAC3D;oBAAgBqH;oBAAYC;iBAAY;YAE7C;QACF,OAAO;YACL,MAAMrH,kBAAkB4G,IAAIE,KAAK,CAAC;YAClC,MAAMrD,WAAY,MAAM,IAAI,CAACJ,EAAE,GAAGK,KAAK,CACrC,CAAC,2FAA2F,CAAC,EAC7F;gBAAC1D;aAAgB;YAEnB,MAAMqH,cACJL,YAAY1B,YAAY0B,UAAUvD,SAASjC,MAAM,GAAG,IAAIiC,QAAQ,CAAC,EAAE,CAAEuD,OAAO,GAAG,IAAI;YACrF,IAAIvD,SAASjC,MAAM,GAAG,GAAG;gBACvB,MAAM,IAAI,CAAC6B,EAAE,GAAGK,KAAK,CACnB,CAAC,oGAAoG,CAAC,EACtG;oBAAC0D;oBAAYC;oBAAarH;iBAAgB;YAE9C,OAAO;gBACL,MAAM,IAAI,CAACqD,EAAE,GAAGK,KAAK,CACnB,CAAC,uGAAuG,CAAC,EACzG;oBAAC1D;oBAAiBoH;oBAAYC;iBAAY;YAE9C;QACF;IACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nest-batch/typeorm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "TypeORM 1.0.0 adapter SLOT for @nest-batch/core — JobRepository and TransactionManager interface shape, paired with @nest-batch/postgresql (Postgres driver) or @nest-batch/mysql (MySQL driver).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "easdkr",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist/src",
|
|
27
27
|
"src",
|
|
28
|
-
"README.md"
|
|
28
|
+
"README.md",
|
|
29
|
+
"README.ko.md"
|
|
29
30
|
],
|
|
30
31
|
"publishConfig": {
|
|
31
32
|
"access": "public"
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"peerDependencies": {
|
|
34
35
|
"@nestjs/common": "^10 || ^11",
|
|
35
36
|
"typeorm": "^1.0.0",
|
|
36
|
-
"@nest-batch/core": "^0.2.
|
|
37
|
+
"@nest-batch/core": "^0.2.4"
|
|
37
38
|
},
|
|
38
39
|
"peerDependenciesMeta": {
|
|
39
40
|
"typeorm": {
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"typescript": "^5.5.0",
|
|
59
60
|
"unplugin-swc": "^1.5.0",
|
|
60
61
|
"vitest": "^2.0.0",
|
|
61
|
-
"@nest-batch/core": "0.2.
|
|
62
|
+
"@nest-batch/core": "0.2.4"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
65
|
"build": "swc src -d dist --config-file ../../.swcrc && tsc --emitDeclarationOnly -p tsconfig.build.json",
|
|
@@ -6,8 +6,8 @@ import { Entity, PrimaryColumn, Column, Index } from 'typeorm';
|
|
|
6
6
|
* One row per logical job instance. Uniqueness is enforced on
|
|
7
7
|
* (jobName, jobKey) so that the same canonical key resolves to the
|
|
8
8
|
* same instance across restarts. The composite unique index is
|
|
9
|
-
* declared on the entity
|
|
10
|
-
*
|
|
9
|
+
* declared on the entity so host-owned TypeORM migrations can
|
|
10
|
+
* generate the matching database constraint.
|
|
11
11
|
*/
|
|
12
12
|
@Entity('batch_job_instance')
|
|
13
13
|
@Index('batch_job_instance_job_name_job_key_unique', ['jobName', 'jobKey'], { unique: true })
|
|
@@ -24,10 +24,9 @@ export class JobInstanceEntity {
|
|
|
24
24
|
@Column({
|
|
25
25
|
name: 'created_at',
|
|
26
26
|
// `datetime` is portable across PostgreSQL and SQLite (the test
|
|
27
|
-
// driver).
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
// compared with sub-second precision in queries.
|
|
27
|
+
// driver). Hosts that generate PostgreSQL migrations can map the
|
|
28
|
+
// same logical column to timestamptz in their own migration
|
|
29
|
+
// pipeline.
|
|
31
30
|
type: 'datetime',
|
|
32
31
|
default: () => 'CURRENT_TIMESTAMP',
|
|
33
32
|
})
|
package/src/index.ts
CHANGED
|
@@ -29,14 +29,18 @@
|
|
|
29
29
|
// },
|
|
30
30
|
// });
|
|
31
31
|
//
|
|
32
|
-
// The
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
|
|
32
|
+
// The TypeORM entity tuple stays in this package because it is the
|
|
33
|
+
// schema contract consumed by a host-owned TypeORM DataSource. Apps
|
|
34
|
+
// generate and own their runnable migration files in their own
|
|
35
|
+
// migration workflow. Driver siblings bind the
|
|
36
|
+
// `TypeOrmDriverProvider` token to a concrete database connection.
|
|
37
|
+
import { BATCH_META_ENTITIES } from './entities';
|
|
38
|
+
|
|
38
39
|
export { TypeOrmJobRepository } from './repository/typeorm-job-repository';
|
|
39
40
|
export type { TypeOrmTransactionContext } from './transaction/typeorm-transaction-manager';
|
|
40
41
|
export { TypeOrmTransactionManager } from './transaction/typeorm-transaction-manager';
|
|
41
42
|
export * from './adapters';
|
|
43
|
+
export { BATCH_META_ENTITIES } from './entities';
|
|
42
44
|
export * from './typeorm.driver-provider';
|
|
45
|
+
|
|
46
|
+
export const batchMetaEntities = (): typeof BATCH_META_ENTITIES => BATCH_META_ENTITIES;
|