Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
/**
* Spec-conformance pinning test for IDMP-08 — Store adapter and LockProvider
* are structural interfaces. Verifies that a plain object implementing the
* shape is accepted everywhere a concrete class would be — no inheritance
* required.
*/
import { describe, expect, it } from "@suaveplan/testing/runner";
import {
DistributedIdempotencyGuard,
IdempotencyGuard,
type IdempotencyRecord,
type IdempotencyStoreAdapter,
type LockProvider,
} from "../src/index.js";
describe("structural adapter interfaces [spec-conformance IDMP-08]", () => {
it("IdempotencyStoreAdapter accepts a plain-object implementation", {
timeout: 5000,
}, async () => {
const records = new Map<string, IdempotencyRecord>();
const store: IdempotencyStoreAdapter = {
async get(key) {
return records.get(key);
},
async set(key, record) {
records.set(key, record);
},
async delete(key) {
return records.delete(key);
},
async cleanup() {
const before = records.size;
records.clear();
return before;
},
};
const guard = new IdempotencyGuard({ store });
const result = await guard.execute("k", async () => "ok");
expect(result).toBe("ok");
expect(records.size).toBe(1);
});
it("LockProvider accepts a plain-object implementation", {
timeout: 5000,
}, async () => {
const records = new Map<string, IdempotencyRecord>();
const store: IdempotencyStoreAdapter = {
async get(key) {
return records.get(key);
},
async set(key, record) {
records.set(key, record);
},
async delete(key) {
return records.delete(key);
},
async cleanup() {
return 0;
},
};
const taken = new Set<string>();
const lockProvider: LockProvider = {
async acquire(resource) {
if (taken.has(resource)) return false;
taken.add(resource);
return true;
},
async release(resource) {
taken.delete(resource);
},
};
const guard = new DistributedIdempotencyGuard({
store,
lockProvider,
retryCount: 0,
retryBaseDelayMs: 0,
});
const result = await guard.execute("k", async () => "ok");
expect(result).toBe("ok");
// Lock released after execution
expect(taken.has("k")).toBe(false);
});
});