@brandboostinggmbh/observable-workflows 0.13.2 → 0.14.0

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/dist/index.d.ts CHANGED
@@ -536,4 +536,29 @@ type R2ExternalBlobStorageOptions = {
536
536
  declare function createR2ExternalBlobStorage(options: R2ExternalBlobStorageOptions): ExternalBlobStorage;
537
537
 
538
538
  //#endregion
539
- export { ConsoleWrapper, DateRangeFilter, ExternalBlobStorage, HandleWorkflowQueueMessageParams, InternalWorkflowContextOptions, Log, PossibleValueTypeNames, PossibleValueTypes, PropertyFilter, QueueWorkflowContextOptions, R2ExternalBlobStorageOptions, Serializer, Step, StepContextOptions, StepCtx, StepWorkflowStatus, StringFilter, ValueTypeMap, WorkflowContext, WorkflowContextInstance, WorkflowContextOptions, WorkflowEnqueueBatchItem, WorkflowFilter, WorkflowFunction, WorkflowProperty, WorkflowPropertyDefinition, WorkflowQueueMessage, WorkflowRun, createLogAccessor, createQueueWorkflowContext, createR2ExternalBlobStorage, createStepContext, createWorkflowContext, defaultIdFactory, defaultSerializer, defineWorkflow, deserializeWithExternalStorage, ensureTables, finalizeWorkflowRecord, insertStepRecordFull, insertWorkflowRecord, pushLogToDB, serializeWithExternalStorage, tryDeserializeObj, updateWorkflowName, upsertWorkflowProperty, workflowTableRowToWorkflowRun };
539
+ //#region src/observableWorkflows/createCleanupManager.d.ts
540
+ type DeleteConfig = {
541
+ deleteWorkflowsOlderThanDays: number;
542
+ delete: {
543
+ successfulWorkflows: boolean;
544
+ failedWorkflows: boolean;
545
+ /** Workflows that are still in progress after a long time, might have failed non-gracefully and are therefore not correctly marked as failed.*/
546
+ inProgressWorkflows: boolean;
547
+ };
548
+ };
549
+ declare const createCleanupManager: (context: {
550
+ D1: D1Database;
551
+ tenantId: string;
552
+ serializer?: Serializer;
553
+ externalBlobStorage?: ExternalBlobStorage;
554
+ }) => {
555
+ countAffectedWorkflows: (config: DeleteConfig) => Promise<{
556
+ count: number;
557
+ }>;
558
+ deleteOldWorkflows: (config: DeleteConfig) => Promise<{
559
+ deletedCount: number;
560
+ }>;
561
+ };
562
+
563
+ //#endregion
564
+ export { ConsoleWrapper, DateRangeFilter, ExternalBlobStorage, HandleWorkflowQueueMessageParams, InternalWorkflowContextOptions, Log, PossibleValueTypeNames, PossibleValueTypes, PropertyFilter, QueueWorkflowContextOptions, R2ExternalBlobStorageOptions, Serializer, Step, StepContextOptions, StepCtx, StepWorkflowStatus, StringFilter, ValueTypeMap, WorkflowContext, WorkflowContextInstance, WorkflowContextOptions, WorkflowEnqueueBatchItem, WorkflowFilter, WorkflowFunction, WorkflowProperty, WorkflowPropertyDefinition, WorkflowQueueMessage, WorkflowRun, createCleanupManager, createLogAccessor, createQueueWorkflowContext, createR2ExternalBlobStorage, createStepContext, createWorkflowContext, defaultIdFactory, defaultSerializer, defineWorkflow, deserializeWithExternalStorage, ensureTables, finalizeWorkflowRecord, insertStepRecordFull, insertWorkflowRecord, pushLogToDB, serializeWithExternalStorage, tryDeserializeObj, updateWorkflowName, upsertWorkflowProperty, workflowTableRowToWorkflowRun };
package/dist/index.js CHANGED
@@ -19,12 +19,19 @@ async function detectSchemaVersion(db) {
19
19
  if (stepTableInfo) {
20
20
  const hasResultRef = stepTableInfo.sql.includes("resultRef");
21
21
  const hasErrorRef = stepTableInfo.sql.includes("errorRef");
22
- if (hasResultRef && hasErrorRef) stepTable = "v2";
22
+ const hasInstanceIdFK = stepTableInfo.sql.includes("FOREIGN KEY (instanceId) REFERENCES WorkflowTable(instanceId)");
23
+ if (hasInstanceIdFK && hasResultRef && hasErrorRef) stepTable = "v5";
24
+ else if (hasResultRef && hasErrorRef) stepTable = "v2";
23
25
  else stepTable = "v1";
24
26
  }
25
27
  const logTableInfo = await db.prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name='LogTable'`).first();
26
28
  let logTable = "missing";
27
- if (logTableInfo) logTable = "v1";
29
+ if (logTableInfo) {
30
+ const hasStepTableCascadeFK = logTableInfo.sql.includes("FOREIGN KEY (instanceId, stepName) REFERENCES StepTable(instanceId, stepName) ON DELETE CASCADE");
31
+ const hasWorkflowTableFK = logTableInfo.sql.includes("FOREIGN KEY (instanceId) REFERENCES WorkflowTable(instanceId) ON DELETE CASCADE");
32
+ if (hasStepTableCascadeFK && hasWorkflowTableFK) logTable = "v5";
33
+ else logTable = "v1";
34
+ }
28
35
  const workflowPropertiesInfo = await db.prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name='WorkflowProperties'`).first();
29
36
  let workflowProperties = "missing";
30
37
  if (workflowPropertiesInfo) workflowProperties = "v1";
@@ -167,7 +174,8 @@ async function migrateStepTable(db, currentVersion) {
167
174
  resultRef TEXT,
168
175
  errorRef TEXT,
169
176
  tenantId TEXT NOT NULL,
170
- PRIMARY KEY (instanceId, stepName)
177
+ PRIMARY KEY (instanceId, stepName),
178
+ FOREIGN KEY (instanceId) REFERENCES WorkflowTable(instanceId) ON DELETE CASCADE
171
179
  )`
172
180
  ).run();
173
181
  return;
@@ -195,8 +203,8 @@ async function migrateLogTable(db, currentVersion) {
195
203
  type TEXT NOT NULL,
196
204
  logOrder INTEGER NOT NULL,
197
205
  tenantId TEXT NOT NULL,
198
- FOREIGN KEY (instanceId, stepName) REFERENCES StepTable(instanceId, stepName)
199
- DEFERRABLE INITIALLY DEFERRED
206
+ FOREIGN KEY (instanceId, stepName) REFERENCES StepTable(instanceId, stepName) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
207
+ FOREIGN KEY (instanceId) REFERENCES WorkflowTable(instanceId) ON DELETE CASCADE
200
208
  )`
201
209
  ).run();
202
210
  return;
@@ -898,6 +906,7 @@ const createLogAccessor = (context) => {
898
906
  WHERE tenantId = ? AND (? IS NULL OR instanceId = ?)
899
907
  `
900
908
  ).bind(context.tenantId, instanceId ?? null, instanceId ?? null).all();
909
+ console.log(`debug getPropertiesKeys: ${JSON.stringify(result)}`);
901
910
  if (!result.results) return [];
902
911
  return result.results.map((row) => ({
903
912
  key: row.key,
@@ -1303,4 +1312,50 @@ function createR2ExternalBlobStorage(options) {
1303
1312
  }
1304
1313
 
1305
1314
  //#endregion
1306
- export { createLogAccessor, createQueueWorkflowContext, createR2ExternalBlobStorage, createStepContext, createWorkflowContext, defaultIdFactory, defaultSerializer, defineWorkflow, deserializeWithExternalStorage, ensureTables, finalizeWorkflowRecord, insertStepRecordFull, insertWorkflowRecord, pushLogToDB, serializeWithExternalStorage, tryDeserializeObj, updateWorkflowName, upsertWorkflowProperty, workflowTableRowToWorkflowRun };
1315
+ //#region src/observableWorkflows/createCleanupManager.ts
1316
+ const createCleanupManager = (context) => {
1317
+ const countAffectedWorkflows = async (config) => {
1318
+ const statuses = [];
1319
+ if (config.delete.successfulWorkflows) statuses.push("completed");
1320
+ if (config.delete.failedWorkflows) statuses.push("failed");
1321
+ if (config.delete.inProgressWorkflows) statuses.push("pending");
1322
+ if (statuses.length === 0) return { count: 0 };
1323
+ const statusPlaceholders = statuses.map(() => "?").join(", ");
1324
+ const result = await context.D1.prepare(
1325
+ /* sql */
1326
+ `
1327
+ SELECT COUNT(*) as count
1328
+ FROM WorkflowTable
1329
+ WHERE tenantId = ?
1330
+ AND startTime < (strftime('%s', 'now', '-' || ? || ' days') * 1000)
1331
+ AND workflowStatus IN (${statusPlaceholders})
1332
+ `
1333
+ ).bind(context.tenantId, config.deleteWorkflowsOlderThanDays, ...statuses).first();
1334
+ return result;
1335
+ };
1336
+ const deleteOldWorkflows = async (config) => {
1337
+ const statuses = [];
1338
+ if (config.delete.successfulWorkflows) statuses.push("completed");
1339
+ if (config.delete.failedWorkflows) statuses.push("failed");
1340
+ if (config.delete.inProgressWorkflows) statuses.push("pending");
1341
+ if (statuses.length === 0) return { deletedCount: 0 };
1342
+ const statusPlaceholders = statuses.map(() => "?").join(", ");
1343
+ const result = await context.D1.prepare(
1344
+ /* sql */
1345
+ `
1346
+ DELETE FROM WorkflowTable
1347
+ WHERE tenantId = ?
1348
+ AND startTime < (strftime('%s', 'now', '-' || ? || ' days') * 1000)
1349
+ AND workflowStatus IN (${statusPlaceholders})
1350
+ `
1351
+ ).bind(context.tenantId, config.deleteWorkflowsOlderThanDays, ...statuses).run();
1352
+ return { deletedCount: result.meta.changes || 0 };
1353
+ };
1354
+ return {
1355
+ countAffectedWorkflows,
1356
+ deleteOldWorkflows
1357
+ };
1358
+ };
1359
+
1360
+ //#endregion
1361
+ export { createCleanupManager, createLogAccessor, createQueueWorkflowContext, createR2ExternalBlobStorage, createStepContext, createWorkflowContext, defaultIdFactory, defaultSerializer, defineWorkflow, deserializeWithExternalStorage, ensureTables, finalizeWorkflowRecord, insertStepRecordFull, insertWorkflowRecord, pushLogToDB, serializeWithExternalStorage, tryDeserializeObj, updateWorkflowName, upsertWorkflowProperty, workflowTableRowToWorkflowRun };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brandboostinggmbh/observable-workflows",
3
- "version": "0.13.2",
3
+ "version": "0.14.0",
4
4
  "description": "My awesome typescript library",
5
5
  "type": "module",
6
6
  "license": "MIT",