@rigkit/engine 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigkit/engine",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -408,6 +408,56 @@ describe("DevMachineEngine workflow runtime", () => {
408
408
  });
409
409
  });
410
410
 
411
+ test("invalidates task cache when handler source changes", async () => {
412
+ const projectDir = mkdtempSync(join(tmpdir(), "rigkit-handler-cache-"));
413
+ const statePath = join(projectDir, ".rigkit", "state.sqlite");
414
+ mkdirSync(join(projectDir, ".rigkit"));
415
+ const writeConfig = (configPath: string, value: string) =>
416
+ writeFileSync(
417
+ configPath,
418
+ `
419
+ import { workflow } from "${import.meta.dir}/index.ts";
420
+
421
+ const app = workflow("handler-cache", { providers: {} });
422
+
423
+ export default app.sequence("root").task("value", async () => {
424
+ return { value: "${value}" };
425
+ });
426
+ `,
427
+ );
428
+
429
+ const firstConfigPath = join(projectDir, "rig.one.config.ts");
430
+ const secondConfigPath = join(projectDir, "rig.two.config.ts");
431
+ writeConfig(firstConfigPath, "one");
432
+ writeConfig(secondConfigPath, "two");
433
+
434
+ const first = await createDevMachineEngine({
435
+ projectDir,
436
+ configPath: firstConfigPath,
437
+ statePath,
438
+ });
439
+ await first.load();
440
+ const applied = await first.apply();
441
+ expect(applied.context.value).toBe("one");
442
+
443
+ const cached = await first.plan();
444
+ expect(cached.cachedNodeCount).toBe(1);
445
+
446
+ const second = await createDevMachineEngine({
447
+ projectDir,
448
+ configPath: secondConfigPath,
449
+ statePath,
450
+ });
451
+ await second.load();
452
+ const changed = await second.plan();
453
+ expect(changed.cachedNodeCount).toBe(0);
454
+ expect(changed.nodes[0]?.status).toBe("pending");
455
+
456
+ const reapplied = await second.apply();
457
+ expect(reapplied.context.value).toBe("two");
458
+ expect(second.listNodeRuns()).toHaveLength(2);
459
+ });
460
+
411
461
  test("stores provider JSON state in Rigkit-owned provider storage", async () => {
412
462
  const projectDir = mkdtempSync(join(tmpdir(), "rigkit-"));
413
463
  const plugin: BaseProviderPlugin = {
package/src/engine.ts CHANGED
@@ -179,6 +179,8 @@ type RuntimeOperationEntry = {
179
179
  readonly run: (input: { workflow?: string; input?: unknown }) => Promise<unknown>;
180
180
  };
181
181
 
182
+ let configImportCounter = 0;
183
+
182
184
  export class DevMachineEngine {
183
185
  private readonly projectDir: string;
184
186
  private readonly configPath: string;
@@ -226,7 +228,7 @@ export class DevMachineEngine {
226
228
  }
227
229
 
228
230
  const moduleUrl = pathToFileURL(this.configPath);
229
- moduleUrl.searchParams.set("t", String(Date.now()));
231
+ moduleUrl.searchParams.set("t", `${Date.now()}-${configImportCounter++}`);
230
232
  const mod = await import(moduleUrl.href);
231
233
  const roots = normalizeDefinitions(mod.default ?? mod.workflow);
232
234
  const loaded = await Promise.all(roots.map((root) => this.resolveWorkflow(root)));
@@ -898,10 +900,13 @@ export class DevMachineEngine {
898
900
  const nodePath = [...input.prefix, input.node.name].join(".");
899
901
  const upstreamRunIds = [...input.state.upstreamRunIds];
900
902
  const nodeKey = hash({
903
+ cache: "task-v2",
901
904
  kind: "task",
902
905
  path: nodePath,
903
906
  name: input.node.name,
904
907
  version: input.node.options?.version ?? null,
908
+ handler: functionFingerprintFor(input.node.handler),
909
+ output: input.node.options?.output ?? null,
905
910
  });
906
911
  const planIndex = input.index.value++;
907
912
 
@@ -1673,18 +1678,36 @@ function collectNodePaths(root: WorkflowNodeDefinition<any, any, any>): string[]
1673
1678
 
1674
1679
  function providerFingerprintFor(workflow: LoadedWorkflow): string {
1675
1680
  return hash({
1681
+ cache: "provider-v2",
1676
1682
  providers: Object.fromEntries(
1677
1683
  Object.entries(workflow.providers).map(([name, provider]) => [
1678
1684
  name,
1679
1685
  {
1680
1686
  providerId: provider.providerId,
1681
1687
  config: provider.config,
1688
+ plugin: providerPluginFingerprint(provider.plugin),
1682
1689
  },
1683
1690
  ]),
1684
1691
  ),
1685
1692
  });
1686
1693
  }
1687
1694
 
1695
+ function providerPluginFingerprint(plugin: unknown): unknown {
1696
+ if (!isBaseProviderPlugin(plugin)) return null;
1697
+ return {
1698
+ providerId: plugin.providerId,
1699
+ createProvider: functionFingerprintFor(plugin.createProvider),
1700
+ };
1701
+ }
1702
+
1703
+ function functionFingerprintFor(fn: Function): { name: string; length: number; source: string } {
1704
+ return {
1705
+ name: fn.name,
1706
+ length: fn.length,
1707
+ source: Function.prototype.toString.call(fn),
1708
+ };
1709
+ }
1710
+
1688
1711
  function sequenceChildren(node: WorkflowNodeDefinition<any, any, any>): readonly WorkflowNodeDefinition<any, any, any>[] {
1689
1712
  return (node as { children?: readonly WorkflowNodeDefinition<any, any, any>[] }).children ?? [];
1690
1713
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const RIGKIT_ENGINE_VERSION = "0.2.0";
1
+ export const RIGKIT_ENGINE_VERSION = "0.2.2";