Initial Commit
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user