hikoutei 0.4.2 → 0.4.3
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/application/sync/outbound/SheetsEffectDispatcher.d.ts +64 -0
- package/dist/application/sync/outbound/SheetsEffectDispatcher.d.ts.map +1 -0
- package/dist/application/sync/outbound/SheetsEffectDispatcher.js +440 -0
- package/dist/application/sync/outbound/SheetsEffectDispatcher.js.map +1 -0
- package/dist/application/sync/service/SyncServiceBootstrap.d.ts +3 -4
- package/dist/application/sync/service/SyncServiceBootstrap.d.ts.map +1 -1
- package/dist/application/sync/service/SyncServiceBootstrap.js +7 -4
- package/dist/application/sync/service/SyncServiceBootstrap.js.map +1 -1
- package/dist/application/sync/telemetry/syncTiming.d.ts +20 -33
- package/dist/application/sync/telemetry/syncTiming.d.ts.map +1 -1
- package/dist/application/sync/telemetry/syncTiming.js +14 -12
- package/dist/application/sync/telemetry/syncTiming.js.map +1 -1
- package/dist/infrastructure/storage/errors.d.ts +10 -5
- package/dist/infrastructure/storage/errors.d.ts.map +1 -1
- package/dist/infrastructure/storage/errors.js +10 -7
- package/dist/infrastructure/storage/errors.js.map +1 -1
- package/dist/infrastructure/storage/index.d.ts +6 -4
- package/dist/infrastructure/storage/index.d.ts.map +1 -1
- package/dist/infrastructure/storage/index.js +3 -2
- package/dist/infrastructure/storage/index.js.map +1 -1
- package/dist/infrastructure/storage/sqlite/schema.d.ts +12 -11
- package/dist/infrastructure/storage/sqlite/schema.d.ts.map +1 -1
- package/dist/infrastructure/storage/sqlite/schema.js +17 -109
- package/dist/infrastructure/storage/sqlite/schema.js.map +1 -1
- package/dist/infrastructure/storage/state/canonical/canonicalCommit.d.ts +2 -2
- package/dist/infrastructure/storage/state/canonical/canonicalCommit.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/canonical/canonicalCommit.js +2 -2
- package/dist/infrastructure/storage/state/canonical/canonicalCommit.js.map +1 -1
- package/dist/infrastructure/storage/state/mapped/mappedPersistenceContext.d.ts +1 -2
- package/dist/infrastructure/storage/state/mapped/mappedPersistenceContext.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/mapped/mappedPersistenceContext.js +1 -2
- package/dist/infrastructure/storage/state/mapped/mappedPersistenceContext.js.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationCanonical.d.ts +1 -1
- package/dist/infrastructure/storage/state/observation/observationCanonical.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationQuarantine.d.ts +1 -1
- package/dist/infrastructure/storage/state/observation/observationQuarantine.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationQuarantine.js +1 -1
- package/dist/infrastructure/storage/state/observation/observationQuarantine.js.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationTypes.d.ts +1 -1
- package/dist/infrastructure/storage/state/observation/observationTypes.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationValidation.d.ts +1 -1
- package/dist/infrastructure/storage/state/observation/observationValidation.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationWriter.d.ts +1 -1
- package/dist/infrastructure/storage/state/observation/observationWriter.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationWriter.js +1 -2
- package/dist/infrastructure/storage/state/observation/observationWriter.js.map +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriter.d.ts +1 -2
- package/dist/infrastructure/storage/state/resolution/resolutionWriter.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriter.js +1 -2
- package/dist/infrastructure/storage/state/resolution/resolutionWriter.js.map +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterContracts.d.ts +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterContracts.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterHelpers.d.ts +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterHelpers.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterHelpers.js +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterHelpers.js.map +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterSql.d.ts +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterSql.d.ts.map +1 -1
- package/dist/infrastructure/storage/state/resolution/resolutionWriterSql.js +2 -2
- package/dist/infrastructure/storage/state/resolution/resolutionWriterSql.js.map +1 -1
- package/dist/infrastructure/storage/sync/shared/spreadsheetAuthority.d.ts +1 -1
- package/dist/infrastructure/storage/sync/shared/spreadsheetAuthority.d.ts.map +1 -1
- package/dist/infrastructure/storage/sync/shared/spreadsheetAuthority.js +1 -1
- package/dist/infrastructure/storage/sync/shared/spreadsheetAuthority.js.map +1 -1
- package/dist/infrastructure/storage/sync/shared/syncRegistry.d.ts +1 -1
- package/dist/infrastructure/storage/sync/shared/syncRegistry.js +1 -1
- package/package.json +13 -7
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.d.ts +0 -66
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.js +0 -123
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.d.ts +0 -111
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.js +0 -369
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorker.d.ts +0 -127
- package/dist/application/sync/outbound/effects/SyncEffectWorker.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorker.js +0 -552
- package/dist/application/sync/outbound/effects/SyncEffectWorker.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.d.ts +0 -85
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.js +0 -74
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.d.ts +0 -31
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.js +0 -222
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerHelpers.d.ts +0 -14
- package/dist/application/sync/outbound/effects/SyncEffectWorkerHelpers.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerHelpers.js +0 -25
- package/dist/application/sync/outbound/effects/SyncEffectWorkerHelpers.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.d.ts +0 -61
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.js +0 -296
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.d.ts +0 -17
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.js +0 -80
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.js.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.d.ts +0 -13
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.d.ts.map +0 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.js +0 -248
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.js.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.d.ts +0 -141
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.d.ts.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.js +0 -318
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.js.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.d.ts +0 -143
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.d.ts.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.js +0 -16
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.js.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.d.ts +0 -33
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.d.ts.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.js +0 -259
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.js.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSupport.d.ts +0 -27
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSupport.d.ts.map +0 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSupport.js +0 -316
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSupport.js.map +0 -1
- package/dist/infrastructure/storage/sync/shared/writerLease.d.ts +0 -76
- package/dist/infrastructure/storage/sync/shared/writerLease.d.ts.map +0 -1
- package/dist/infrastructure/storage/sync/shared/writerLease.js +0 -189
- package/dist/infrastructure/storage/sync/shared/writerLease.js.map +0 -1
- package/docs/advanced-sheets-gateway-concurrency-problem.md +0 -434
- package/docs/architecture.md +0 -224
- package/docs/ci.md +0 -293
- package/docs/code-guidelines.md +0 -248
- package/docs/development.md +0 -74
- package/docs/gateway-removal-inventory.md +0 -147
- package/docs/git-workflow.md +0 -224
- package/docs/google-sheets-sync-scaling-strategy.md +0 -459
- package/docs/mikro-orm-adapter-spike.md +0 -89
- package/docs/quick-start.md +0 -137
- package/docs/sql-layer-plan.md +0 -59
- package/docs/sync-bulk-write-benchmark.md +0 -2117
- package/docs/sync-observability.md +0 -100
- package/docs/task-queue-write-model.md +0 -640
- package/docs/typed-sheets-mvp-scope-2026-06-29.md +0 -490
- package/docs/typed-sheets-plan.md +0 -417
- package/docs/write-and-synchronization-flow.md +0 -179
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SQLite writer lease and fencing token management.
|
|
3
|
-
*
|
|
4
|
-
* Per design concurrency/writer-rpc.md:
|
|
5
|
-
* - Single writer owns all canonical/outbox mutations.
|
|
6
|
-
* - Every mutation CAS-checks the current fencing token.
|
|
7
|
-
* - Lease takeover increments epoch + fencing token.
|
|
8
|
-
* - Stale fencing tokens are rejected even if the affected row hasn't changed.
|
|
9
|
-
*/
|
|
10
|
-
import type { LookupResult } from "../../../../shared/state/types.js";
|
|
11
|
-
import type { SqlExecutor, SqlStorageAdapter } from "../../../../adapter/persistence/contracts/sql.js";
|
|
12
|
-
export interface WriterLease {
|
|
13
|
-
readonly role: string;
|
|
14
|
-
readonly writerId: string;
|
|
15
|
-
readonly writerEpoch: number;
|
|
16
|
-
readonly fencingToken: string;
|
|
17
|
-
readonly leaseUntil: number;
|
|
18
|
-
}
|
|
19
|
-
/** Runtime values for the two observable writer-lease claim outcomes. */
|
|
20
|
-
export declare const WRITER_LEASE_CLAIM_RESULT_KINDS: {
|
|
21
|
-
readonly CLAIMED: "claimed";
|
|
22
|
-
readonly NOT_CLAIMED: "not_claimed";
|
|
23
|
-
};
|
|
24
|
-
/** Closed set of writer-lease claim outcome kinds. */
|
|
25
|
-
export type WriterLeaseClaimResultKind = (typeof WRITER_LEASE_CLAIM_RESULT_KINDS)[keyof typeof WRITER_LEASE_CLAIM_RESULT_KINDS];
|
|
26
|
-
/** Runtime values explaining why a writer-lease claim did not succeed. */
|
|
27
|
-
export declare const WRITER_LEASE_CLAIM_FAILURE_REASONS: {
|
|
28
|
-
readonly ACTIVE_WRITER: "active_writer";
|
|
29
|
-
readonly INITIAL_CLAIM_NOT_APPLIED: "initial_claim_not_applied";
|
|
30
|
-
readonly RENEWAL_RACE_LOST: "renewal_race_lost";
|
|
31
|
-
readonly TAKEOVER_RACE_LOST: "takeover_race_lost";
|
|
32
|
-
};
|
|
33
|
-
/** Closed set of writer-lease claim failure reasons. */
|
|
34
|
-
export type WriterLeaseClaimFailureReason = (typeof WRITER_LEASE_CLAIM_FAILURE_REASONS)[keyof typeof WRITER_LEASE_CLAIM_FAILURE_REASONS];
|
|
35
|
-
export type WriterLeaseClaimResult = {
|
|
36
|
-
readonly kind: typeof WRITER_LEASE_CLAIM_RESULT_KINDS.CLAIMED;
|
|
37
|
-
readonly lease: WriterLease;
|
|
38
|
-
} | {
|
|
39
|
-
readonly kind: typeof WRITER_LEASE_CLAIM_RESULT_KINDS.NOT_CLAIMED;
|
|
40
|
-
readonly reason: WriterLeaseClaimFailureReason;
|
|
41
|
-
};
|
|
42
|
-
export interface ClaimLeaseOptions {
|
|
43
|
-
readonly role: string;
|
|
44
|
-
readonly writerId: string;
|
|
45
|
-
readonly leaseDurationMs: number;
|
|
46
|
-
readonly now: number;
|
|
47
|
-
}
|
|
48
|
-
/** The current lease identity required for a fenced storage mutation. */
|
|
49
|
-
export interface FencingContext {
|
|
50
|
-
readonly role: string;
|
|
51
|
-
readonly writerEpoch: number;
|
|
52
|
-
readonly fencingToken: string;
|
|
53
|
-
readonly now: number;
|
|
54
|
-
}
|
|
55
|
-
/** SQL fragment used to fence mutations against the current writer lease. */
|
|
56
|
-
export declare const FENCE_EXISTS_SQL = "\n SELECT 1 FROM writer_lease\n WHERE role = ? AND writer_epoch = ? AND fencing_token = ? AND lease_until > ?\n";
|
|
57
|
-
/** Returns the parameter tuple shared by every fenced SQL statement. */
|
|
58
|
-
export declare function fenceParameters(fence: FencingContext): readonly [string, number, string, number];
|
|
59
|
-
/**
|
|
60
|
-
* Claims or renews a writer lease inside an already-active async SQL context.
|
|
61
|
-
*
|
|
62
|
-
* Call it from a broader adapter transaction when the lease claim must be
|
|
63
|
-
* atomic with an entity, canonical-state, or outbox mutation.
|
|
64
|
-
*/
|
|
65
|
-
export declare function claimWriterLeaseWithSql(sql: SqlExecutor, options: ClaimLeaseOptions): Promise<WriterLeaseClaimResult>;
|
|
66
|
-
/** Claims or renews a writer lease in one adapter-owned transaction. */
|
|
67
|
-
export declare function claimWriterLeaseWithAdapter(storage: SqlStorageAdapter, options: ClaimLeaseOptions): Promise<WriterLeaseClaimResult>;
|
|
68
|
-
/** Reads a writer lease through an already-active async SQL context. */
|
|
69
|
-
export declare function readWriterLeaseWithSql(sql: SqlExecutor, role: string): Promise<LookupResult<WriterLease>>;
|
|
70
|
-
/** Reads a writer lease through a fresh adapter read context. */
|
|
71
|
-
export declare function readWriterLeaseWithAdapter(storage: SqlStorageAdapter, role: string): Promise<LookupResult<WriterLease>>;
|
|
72
|
-
/** Checks a fencing token inside an already-active async SQL context. */
|
|
73
|
-
export declare function isFencingValidWithSql(sql: SqlExecutor, fence: FencingContext): Promise<boolean>;
|
|
74
|
-
/** Checks a fencing token through a fresh adapter read context. */
|
|
75
|
-
export declare function isFencingValidWithAdapter(storage: SqlStorageAdapter, fence: FencingContext): Promise<boolean>;
|
|
76
|
-
//# sourceMappingURL=writerLease.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"writerLease.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/storage/sync/shared/writerLease.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SQLite writer lease and fencing token management.
|
|
3
|
-
*
|
|
4
|
-
* Per design concurrency/writer-rpc.md:
|
|
5
|
-
* - Single writer owns all canonical/outbox mutations.
|
|
6
|
-
* - Every mutation CAS-checks the current fencing token.
|
|
7
|
-
* - Lease takeover increments epoch + fencing token.
|
|
8
|
-
* - Stale fencing tokens are rejected even if the affected row hasn't changed.
|
|
9
|
-
*/
|
|
10
|
-
import { STORAGE_ERROR_CODES, StorageError } from "../../errors.js";
|
|
11
|
-
import { LOOKUP_RESULT_KINDS } from "../../../../shared/state/constants.js";
|
|
12
|
-
import { withSqlSavepoint } from "../../sqlite/sqlTransaction.js";
|
|
13
|
-
const READ_WRITER_LEASE_SQL = "SELECT role, writer_id, writer_epoch, fencing_token, lease_until FROM writer_lease WHERE role = ?";
|
|
14
|
-
const INSERT_WRITER_LEASE_SQL = `
|
|
15
|
-
INSERT INTO writer_lease (role, writer_id, writer_epoch, fencing_token, lease_until)
|
|
16
|
-
VALUES (?, ?, ?, ?, ?)
|
|
17
|
-
`;
|
|
18
|
-
const RENEW_WRITER_LEASE_SQL = `
|
|
19
|
-
UPDATE writer_lease
|
|
20
|
-
SET lease_until = ?
|
|
21
|
-
WHERE role = ? AND writer_id = ? AND writer_epoch = ?
|
|
22
|
-
AND fencing_token = ? AND lease_until > ?
|
|
23
|
-
`;
|
|
24
|
-
const TAKEOVER_WRITER_LEASE_SQL = `
|
|
25
|
-
UPDATE writer_lease
|
|
26
|
-
SET writer_id = ?, writer_epoch = ?, fencing_token = ?, lease_until = ?
|
|
27
|
-
WHERE role = ? AND writer_epoch = ? AND fencing_token = ? AND lease_until <= ?
|
|
28
|
-
`;
|
|
29
|
-
/** Runtime values for the two observable writer-lease claim outcomes. */
|
|
30
|
-
export const WRITER_LEASE_CLAIM_RESULT_KINDS = {
|
|
31
|
-
CLAIMED: "claimed",
|
|
32
|
-
NOT_CLAIMED: "not_claimed",
|
|
33
|
-
};
|
|
34
|
-
/** Runtime values explaining why a writer-lease claim did not succeed. */
|
|
35
|
-
export const WRITER_LEASE_CLAIM_FAILURE_REASONS = {
|
|
36
|
-
ACTIVE_WRITER: "active_writer",
|
|
37
|
-
INITIAL_CLAIM_NOT_APPLIED: "initial_claim_not_applied",
|
|
38
|
-
RENEWAL_RACE_LOST: "renewal_race_lost",
|
|
39
|
-
TAKEOVER_RACE_LOST: "takeover_race_lost",
|
|
40
|
-
};
|
|
41
|
-
/** SQL fragment used to fence mutations against the current writer lease. */
|
|
42
|
-
export const FENCE_EXISTS_SQL = `
|
|
43
|
-
SELECT 1 FROM writer_lease
|
|
44
|
-
WHERE role = ? AND writer_epoch = ? AND fencing_token = ? AND lease_until > ?
|
|
45
|
-
`;
|
|
46
|
-
/** Returns the parameter tuple shared by every fenced SQL statement. */
|
|
47
|
-
export function fenceParameters(fence) {
|
|
48
|
-
return [fence.role, fence.writerEpoch, fence.fencingToken, fence.now];
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Claims or renews a writer lease inside an already-active async SQL context.
|
|
52
|
-
*
|
|
53
|
-
* Call it from a broader adapter transaction when the lease claim must be
|
|
54
|
-
* atomic with an entity, canonical-state, or outbox mutation.
|
|
55
|
-
*/
|
|
56
|
-
export async function claimWriterLeaseWithSql(sql, options) {
|
|
57
|
-
validateClaimOptions(options);
|
|
58
|
-
return withSqlSavepoint(sql, "claim_writer_lease", async () => {
|
|
59
|
-
const existing = await readLeaseRowWithSql(sql, options.role);
|
|
60
|
-
const newLeaseUntil = options.now + options.leaseDurationMs;
|
|
61
|
-
if (existing === undefined) {
|
|
62
|
-
const lease = makeLease(options.role, options.writerId, 1, newLeaseUntil);
|
|
63
|
-
const result = await sql.run(INSERT_WRITER_LEASE_SQL, [
|
|
64
|
-
lease.role,
|
|
65
|
-
lease.writerId,
|
|
66
|
-
lease.writerEpoch,
|
|
67
|
-
lease.fencingToken,
|
|
68
|
-
lease.leaseUntil,
|
|
69
|
-
]);
|
|
70
|
-
return result.changes === 1
|
|
71
|
-
? { kind: WRITER_LEASE_CLAIM_RESULT_KINDS.CLAIMED, lease }
|
|
72
|
-
: {
|
|
73
|
-
kind: WRITER_LEASE_CLAIM_RESULT_KINDS.NOT_CLAIMED,
|
|
74
|
-
reason: WRITER_LEASE_CLAIM_FAILURE_REASONS.INITIAL_CLAIM_NOT_APPLIED,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if (existing.writer_id === options.writerId && existing.lease_until > options.now) {
|
|
78
|
-
const result = await sql.run(RENEW_WRITER_LEASE_SQL, [
|
|
79
|
-
newLeaseUntil,
|
|
80
|
-
options.role,
|
|
81
|
-
options.writerId,
|
|
82
|
-
existing.writer_epoch,
|
|
83
|
-
existing.fencing_token,
|
|
84
|
-
options.now,
|
|
85
|
-
]);
|
|
86
|
-
return result.changes === 1
|
|
87
|
-
? {
|
|
88
|
-
kind: WRITER_LEASE_CLAIM_RESULT_KINDS.CLAIMED,
|
|
89
|
-
lease: {
|
|
90
|
-
role: existing.role,
|
|
91
|
-
writerId: existing.writer_id,
|
|
92
|
-
writerEpoch: existing.writer_epoch,
|
|
93
|
-
fencingToken: existing.fencing_token,
|
|
94
|
-
leaseUntil: newLeaseUntil,
|
|
95
|
-
},
|
|
96
|
-
}
|
|
97
|
-
: {
|
|
98
|
-
kind: WRITER_LEASE_CLAIM_RESULT_KINDS.NOT_CLAIMED,
|
|
99
|
-
reason: WRITER_LEASE_CLAIM_FAILURE_REASONS.RENEWAL_RACE_LOST,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
if (existing.lease_until > options.now) {
|
|
103
|
-
return {
|
|
104
|
-
kind: WRITER_LEASE_CLAIM_RESULT_KINDS.NOT_CLAIMED,
|
|
105
|
-
reason: WRITER_LEASE_CLAIM_FAILURE_REASONS.ACTIVE_WRITER,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
const takeover = makeLease(options.role, options.writerId, existing.writer_epoch + 1, newLeaseUntil);
|
|
109
|
-
const result = await sql.run(TAKEOVER_WRITER_LEASE_SQL, [
|
|
110
|
-
takeover.writerId,
|
|
111
|
-
takeover.writerEpoch,
|
|
112
|
-
takeover.fencingToken,
|
|
113
|
-
takeover.leaseUntil,
|
|
114
|
-
options.role,
|
|
115
|
-
existing.writer_epoch,
|
|
116
|
-
existing.fencing_token,
|
|
117
|
-
options.now,
|
|
118
|
-
]);
|
|
119
|
-
return result.changes === 1
|
|
120
|
-
? { kind: WRITER_LEASE_CLAIM_RESULT_KINDS.CLAIMED, lease: takeover }
|
|
121
|
-
: {
|
|
122
|
-
kind: WRITER_LEASE_CLAIM_RESULT_KINDS.NOT_CLAIMED,
|
|
123
|
-
reason: WRITER_LEASE_CLAIM_FAILURE_REASONS.TAKEOVER_RACE_LOST,
|
|
124
|
-
};
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
/** Claims or renews a writer lease in one adapter-owned transaction. */
|
|
128
|
-
export async function claimWriterLeaseWithAdapter(storage, options) {
|
|
129
|
-
return storage.transaction(({ sql }) => claimWriterLeaseWithSql(sql, options));
|
|
130
|
-
}
|
|
131
|
-
/** Reads a writer lease through an already-active async SQL context. */
|
|
132
|
-
export async function readWriterLeaseWithSql(sql, role) {
|
|
133
|
-
const row = await readLeaseRowWithSql(sql, role);
|
|
134
|
-
return row === undefined
|
|
135
|
-
? { kind: LOOKUP_RESULT_KINDS.NOT_FOUND }
|
|
136
|
-
: {
|
|
137
|
-
kind: LOOKUP_RESULT_KINDS.FOUND,
|
|
138
|
-
value: {
|
|
139
|
-
role: row.role,
|
|
140
|
-
writerId: row.writer_id,
|
|
141
|
-
writerEpoch: row.writer_epoch,
|
|
142
|
-
fencingToken: row.fencing_token,
|
|
143
|
-
leaseUntil: row.lease_until,
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
/** Reads a writer lease through a fresh adapter read context. */
|
|
148
|
-
export async function readWriterLeaseWithAdapter(storage, role) {
|
|
149
|
-
return storage.read(({ sql }) => readWriterLeaseWithSql(sql, role));
|
|
150
|
-
}
|
|
151
|
-
/** Checks a fencing token inside an already-active async SQL context. */
|
|
152
|
-
export async function isFencingValidWithSql(sql, fence) {
|
|
153
|
-
const lease = await readWriterLeaseWithSql(sql, fence.role);
|
|
154
|
-
if (lease.kind === LOOKUP_RESULT_KINDS.NOT_FOUND)
|
|
155
|
-
return false;
|
|
156
|
-
return (lease.value.writerEpoch === fence.writerEpoch &&
|
|
157
|
-
lease.value.fencingToken === fence.fencingToken &&
|
|
158
|
-
lease.value.leaseUntil > fence.now);
|
|
159
|
-
}
|
|
160
|
-
/** Checks a fencing token through a fresh adapter read context. */
|
|
161
|
-
export async function isFencingValidWithAdapter(storage, fence) {
|
|
162
|
-
return storage.read(({ sql }) => isFencingValidWithSql(sql, fence));
|
|
163
|
-
}
|
|
164
|
-
function readLeaseRowWithSql(sql, role) {
|
|
165
|
-
return sql.get(READ_WRITER_LEASE_SQL, [role]);
|
|
166
|
-
}
|
|
167
|
-
function makeLease(role, writerId, writerEpoch, leaseUntil) {
|
|
168
|
-
return {
|
|
169
|
-
role,
|
|
170
|
-
writerId,
|
|
171
|
-
writerEpoch,
|
|
172
|
-
// Include the owner identity as well as the monotonically increasing epoch;
|
|
173
|
-
// equal epochs from different roles must never share a remote authority token.
|
|
174
|
-
fencingToken: `fence-${writerEpoch}:${writerId}`,
|
|
175
|
-
leaseUntil,
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
function validateClaimOptions(options) {
|
|
179
|
-
if (!Number.isSafeInteger(options.now) || options.now < 0) {
|
|
180
|
-
throw new StorageError(STORAGE_ERROR_CODES.INVALID_WRITER_LEASE_OPTIONS, "writer lease now must be a non-negative safe integer");
|
|
181
|
-
}
|
|
182
|
-
if (!Number.isSafeInteger(options.leaseDurationMs) || options.leaseDurationMs <= 0) {
|
|
183
|
-
throw new StorageError(STORAGE_ERROR_CODES.INVALID_WRITER_LEASE_OPTIONS, "writer lease duration must be a positive safe integer");
|
|
184
|
-
}
|
|
185
|
-
if (options.role.length === 0 || options.writerId.length === 0) {
|
|
186
|
-
throw new StorageError(STORAGE_ERROR_CODES.INVALID_WRITER_LEASE_OPTIONS, "writer lease role and writer ID are required");
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
//# sourceMappingURL=writerLease.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"writerLease.js","sourceRoot":"","sources":["../../../../../src/infrastructure/storage/sync/shared/writerLease.ts"],"names":[],"mappings":"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"}
|