@falcondev-oss/workflow 0.9.1 → 0.10.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.
Files changed (2) hide show
  1. package/dist/index.mjs +12 -6
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -7296,7 +7296,7 @@ var require_parser = /* @__PURE__ */ __commonJSMin(((exports, module) => {
7296
7296
  }));
7297
7297
 
7298
7298
  //#endregion
7299
- //#region node_modules/.pnpm/groupmq@1.1.1-next.2_patch_hash=0f055dcc6e397c02b849be5416debe7d948309b119c1f5282e0cfc6f2a063543_ioredis@5.9.2/node_modules/groupmq/dist/index.js
7299
+ //#region node_modules/.pnpm/groupmq@1.1.1-next.2_patch_hash=1f311e9b6cc731809ddc67335576540abb3c2e90f98c33be84e8bb3c8113391c_ioredis@5.9.2/node_modules/groupmq/dist/index.js
7300
7300
  var import_parser = /* @__PURE__ */ __toESM$1(require_parser(), 1);
7301
7301
  const __INLINED_LUA_SCRIPTS__ = {
7302
7302
  "change-delay": "-- argv: ns, jobId, newDelayUntil, now\nlocal ns = KEYS[1]\nlocal jobId = ARGV[1]\nlocal newDelayUntil = tonumber(ARGV[2])\nlocal now = tonumber(ARGV[3])\n\nlocal jobKey = ns .. \":job:\" .. jobId\nlocal delayedKey = ns .. \":delayed\"\nlocal readyKey = ns .. \":ready\"\n\n-- Check if job exists\nlocal exists = redis.call(\"EXISTS\", jobKey)\nif exists == 0 then\n return 0\nend\n\nlocal groupId = redis.call(\"HGET\", jobKey, \"groupId\")\nif not groupId then\n return 0\nend\n\nlocal gZ = ns .. \":g:\" .. groupId\n\n-- Update job's delayUntil field\nredis.call(\"HSET\", jobKey, \"delayUntil\", tostring(newDelayUntil))\n\n-- Check if job is currently in delayed set\nlocal inDelayed = redis.call(\"ZSCORE\", delayedKey, jobId)\n\nif newDelayUntil > 0 and newDelayUntil > now then\n -- Job should be delayed\n redis.call(\"HSET\", jobKey, \"status\", \"delayed\")\n if inDelayed then\n -- Update existing delay\n redis.call(\"ZADD\", delayedKey, newDelayUntil, jobId)\n else\n -- Move to delayed\n redis.call(\"ZADD\", delayedKey, newDelayUntil, jobId)\n -- If this is the head job, remove group from ready\n local head = redis.call(\"ZRANGE\", gZ, 0, 0)\n if head and #head > 0 and head[1] == jobId then\n redis.call(\"ZREM\", readyKey, groupId)\n end\n end\nelse\n -- Job should be ready immediately\n redis.call(\"HSET\", jobKey, \"status\", \"waiting\")\n if inDelayed then\n -- Remove from delayed\n redis.call(\"ZREM\", delayedKey, jobId)\n -- If this is the head job, ensure group is in ready\n local head = redis.call(\"ZRANGE\", gZ, 0, 0, \"WITHSCORES\")\n if head and #head >= 2 and head[1] == jobId then\n local headScore = tonumber(head[2])\n redis.call(\"ZADD\", readyKey, headScore, groupId)\n end\n end\nend\n\nreturn 1\n\n\n",
@@ -8782,7 +8782,7 @@ var Queue = class {
8782
8782
  async addRepeatingJob(opts) {
8783
8783
  if (!opts.repeat) throw new Error("Repeat options are required for repeating jobs");
8784
8784
  const now = Date.now();
8785
- const repeatKey = `${opts.groupId}:${JSON.stringify(opts.repeat)}:${now}:${Math.random().toString(36).slice(2)}`;
8785
+ const repeatKey = `${opts.groupId}:${now}:${Math.random().toString(36).slice(2)}`;
8786
8786
  let nextRunTime;
8787
8787
  if ("every" in opts.repeat) nextRunTime = now + opts.repeat.every;
8788
8788
  else nextRunTime = this.getNextCronTime(opts.repeat.pattern, now);
@@ -8799,7 +8799,7 @@ var Queue = class {
8799
8799
  const repeatJobKey = `${this.ns}:repeat:${repeatKey}`;
8800
8800
  await this.r.set(repeatJobKey, JSON.stringify(repeatJobData));
8801
8801
  await this.r.zadd(`${this.ns}:repeat:schedule`, nextRunTime, repeatKey);
8802
- const lookupKey = `${this.ns}:repeat:lookup:${opts.groupId}:${JSON.stringify(opts.repeat)}`;
8802
+ const lookupKey = `${this.ns}:repeat:lookup:${opts.groupId}`;
8803
8803
  await this.r.set(lookupKey, repeatKey);
8804
8804
  const repeatId = `repeat:${repeatKey}`;
8805
8805
  const jobHashKey = `${this.ns}:job:${repeatId}`;
@@ -8821,9 +8821,9 @@ var Queue = class {
8821
8821
  /**
8822
8822
  * Remove a repeating job
8823
8823
  */
8824
- async removeRepeatingJob(groupId, repeat) {
8824
+ async removeRepeatingJob(groupId) {
8825
8825
  try {
8826
- const lookupKey = `${this.ns}:repeat:lookup:${groupId}:${JSON.stringify(repeat)}`;
8826
+ const lookupKey = `${this.ns}:repeat:lookup:${groupId}`;
8827
8827
  const repeatKey = await this.r.get(lookupKey);
8828
8828
  if (!repeatKey) return false;
8829
8829
  const repeatJobKey = `${this.ns}:repeat:${repeatKey}`;
@@ -9819,6 +9819,10 @@ var Workflow = class {
9819
9819
  const parsedInput = this.opts.schema && await this.opts.schema["~standard"].validate(input);
9820
9820
  if (parsedInput?.issues) throw new Error("Invalid workflow input");
9821
9821
  const queue = await this.getOrCreateQueue();
9822
+ const groupId = opts?.groupId ?? await this.opts.getGroupId?.(parsedInput?.value) ?? randomUUID();
9823
+ if (opts?.repeat) {
9824
+ if (await queue.removeRepeatingJob(groupId)) Settings.logger?.debug?.(`[${this.opts.id}] Removed existing repeating job with groupId '${groupId}' before adding new one with schedule ${JSON.stringify(opts.repeat)}`);
9825
+ }
9822
9826
  return runWithTracing(`workflow-producer/${this.opts.id}`, {
9823
9827
  attributes: { "workflow.id": this.opts.id },
9824
9828
  kind: SpanKind.PRODUCER
@@ -9827,7 +9831,6 @@ var Workflow = class {
9827
9831
  propagation.inject(context.active(), tracingHeaders);
9828
9832
  const orderMs = opts?.orderMs ?? (opts?.priority === "high" ? 0 : void 0) ?? this.opts.jobOptions?.orderMs ?? (this.opts.jobOptions?.priority === "high" ? 0 : void 0);
9829
9833
  return new WorkflowJob({ job: await queue.add({
9830
- groupId: await this.opts.getGroupId?.(parsedInput?.value) ?? randomUUID(),
9831
9834
  data: serialize$1({
9832
9835
  input: parsedInput?.value,
9833
9836
  stepData: {},
@@ -9835,6 +9838,7 @@ var Workflow = class {
9835
9838
  }),
9836
9839
  ...this.opts.jobOptions,
9837
9840
  ...opts,
9841
+ groupId,
9838
9842
  orderMs
9839
9843
  }) });
9840
9844
  });
@@ -9854,6 +9858,7 @@ var Workflow = class {
9854
9858
  async "runCron"(scheduleId, cron, input, opts) {
9855
9859
  return this.run(input, {
9856
9860
  groupId: scheduleId,
9861
+ jobId: scheduleId,
9857
9862
  repeat: { pattern: cron },
9858
9863
  ...opts
9859
9864
  });
@@ -9861,6 +9866,7 @@ var Workflow = class {
9861
9866
  async "runEvery"(scheduleId, everyMs, input, opts) {
9862
9867
  return this.run(input, {
9863
9868
  groupId: scheduleId,
9869
+ jobId: scheduleId,
9864
9870
  repeat: { every: everyMs },
9865
9871
  ...opts
9866
9872
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@falcondev-oss/workflow",
3
3
  "type": "module",
4
- "version": "0.9.1",
4
+ "version": "0.10.0",
5
5
  "description": "Simple type-safe queue worker with durable execution using Redis.",
6
6
  "license": "MIT",
7
7
  "repository": "github:falcondev-oss/workflow",