hikoutei 0.10.1-dev → 0.10.3-dev

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 (177) hide show
  1. package/dist/composition/localRuntime.js +2 -2
  2. package/dist/composition/localRuntime.js.map +1 -1
  3. package/dist/contracts/domain/model/constants.d.ts +15 -0
  4. package/dist/contracts/domain/model/constants.d.ts.map +1 -1
  5. package/dist/contracts/domain/model/constants.js +13 -0
  6. package/dist/contracts/domain/model/constants.js.map +1 -1
  7. package/dist/contracts/shared/observability/internalLog.d.ts.map +1 -0
  8. package/dist/contracts/shared/observability/internalLog.js.map +1 -0
  9. package/dist/contracts/shared/observability/logEvents.d.ts.map +1 -0
  10. package/dist/contracts/shared/observability/logEvents.js.map +1 -0
  11. package/dist/contracts/sheets/mutationCoordinator/CoordinatedSheetsProvider.js +1 -1
  12. package/dist/contracts/sheets/mutationCoordinator/CoordinatedSheetsProvider.js.map +1 -1
  13. package/dist/contracts/sheets/mutationCoordinator/laneTelemetry.d.ts +1 -1
  14. package/dist/contracts/sheets/mutationCoordinator/laneTelemetry.d.ts.map +1 -1
  15. package/dist/contracts/sheets/mutationCoordinator/laneTelemetry.js +1 -1
  16. package/dist/contracts/sheets/mutationCoordinator/laneTelemetry.js.map +1 -1
  17. package/dist/contracts/sheets/timing.d.ts +4 -37
  18. package/dist/contracts/sheets/timing.d.ts.map +1 -1
  19. package/dist/contracts/sheets/timing.js +4 -18
  20. package/dist/contracts/sheets/timing.js.map +1 -1
  21. package/dist/internal/syncStatus.d.ts.map +1 -1
  22. package/dist/internal/syncStatus.js +1 -2
  23. package/dist/internal/syncStatus.js.map +1 -1
  24. package/dist/orm/persistence/projection/projectionEffects.d.ts.map +1 -1
  25. package/dist/orm/persistence/projection/projectionEffects.js +2 -2
  26. package/dist/orm/persistence/projection/projectionEffects.js.map +1 -1
  27. package/dist/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.d.ts +2 -0
  28. package/dist/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.d.ts.map +1 -1
  29. package/dist/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.js +21 -4
  30. package/dist/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.js.map +1 -1
  31. package/dist/sheets/providers/google-sheets-api/constants.d.ts +13 -2
  32. package/dist/sheets/providers/google-sheets-api/constants.d.ts.map +1 -1
  33. package/dist/sheets/providers/google-sheets-api/constants.js +17 -2
  34. package/dist/sheets/providers/google-sheets-api/constants.js.map +1 -1
  35. package/dist/sheets/providers/google-sheets-api/errors.js +2 -2
  36. package/dist/sheets/providers/google-sheets-api/errors.js.map +1 -1
  37. package/dist/sheets/providers/google-sheets-api/index.d.ts +1 -1
  38. package/dist/sheets/providers/google-sheets-api/index.d.ts.map +1 -1
  39. package/dist/sheets/providers/google-sheets-api/index.js +1 -1
  40. package/dist/sheets/providers/google-sheets-api/index.js.map +1 -1
  41. package/dist/sheets/providers/google-sheets-api/model/batchBuilder.d.ts.map +1 -1
  42. package/dist/sheets/providers/google-sheets-api/model/batchBuilder.js +7 -7
  43. package/dist/sheets/providers/google-sheets-api/model/batchBuilder.js.map +1 -1
  44. package/dist/sheets/providers/google-sheets-api/model/observation.d.ts +3 -3
  45. package/dist/sheets/providers/google-sheets-api/model/observation.d.ts.map +1 -1
  46. package/dist/sheets/providers/google-sheets-api/model/observation.js +11 -8
  47. package/dist/sheets/providers/google-sheets-api/model/observation.js.map +1 -1
  48. package/dist/sheets/providers/google-sheets-api/model/plannerReceipt.d.ts +6 -5
  49. package/dist/sheets/providers/google-sheets-api/model/plannerReceipt.d.ts.map +1 -1
  50. package/dist/sheets/providers/google-sheets-api/model/plannerReceipt.js +97 -43
  51. package/dist/sheets/providers/google-sheets-api/model/plannerReceipt.js.map +1 -1
  52. package/dist/sheets/providers/google-sheets-api/model/postcondition.d.ts +8 -5
  53. package/dist/sheets/providers/google-sheets-api/model/postcondition.d.ts.map +1 -1
  54. package/dist/sheets/providers/google-sheets-api/model/postcondition.js +50 -60
  55. package/dist/sheets/providers/google-sheets-api/model/postcondition.js.map +1 -1
  56. package/dist/sheets/providers/google-sheets-api/model/preflightContext.d.ts +5 -6
  57. package/dist/sheets/providers/google-sheets-api/model/preflightContext.d.ts.map +1 -1
  58. package/dist/sheets/providers/google-sheets-api/model/preflightContext.js +22 -15
  59. package/dist/sheets/providers/google-sheets-api/model/preflightContext.js.map +1 -1
  60. package/dist/sheets/providers/google-sheets-api/model/preflightVerify.d.ts +2 -2
  61. package/dist/sheets/providers/google-sheets-api/model/preflightVerify.d.ts.map +1 -1
  62. package/dist/sheets/providers/google-sheets-api/model/preflightVerify.js +10 -7
  63. package/dist/sheets/providers/google-sheets-api/model/preflightVerify.js.map +1 -1
  64. package/dist/sheets/providers/google-sheets-api/operations/applyEffects.d.ts.map +1 -1
  65. package/dist/sheets/providers/google-sheets-api/operations/applyEffects.js +2 -3
  66. package/dist/sheets/providers/google-sheets-api/operations/applyEffects.js.map +1 -1
  67. package/dist/sheets/providers/google-sheets-api/operations/fastAppend.d.ts.map +1 -1
  68. package/dist/sheets/providers/google-sheets-api/operations/fastAppend.js +2 -3
  69. package/dist/sheets/providers/google-sheets-api/operations/fastAppend.js.map +1 -1
  70. package/dist/sheets/providers/google-sheets-api/operations/preflightOp.d.ts.map +1 -1
  71. package/dist/sheets/providers/google-sheets-api/operations/preflightOp.js +2 -2
  72. package/dist/sheets/providers/google-sheets-api/operations/preflightOp.js.map +1 -1
  73. package/dist/sheets/providers/google-sheets-api/operations/provisioning.d.ts.map +1 -1
  74. package/dist/sheets/providers/google-sheets-api/operations/provisioning.js +2 -2
  75. package/dist/sheets/providers/google-sheets-api/operations/provisioning.js.map +1 -1
  76. package/dist/sheets/providers/google-sheets-api/operations/readRows.js +1 -1
  77. package/dist/sheets/providers/google-sheets-api/operations/readRows.js.map +1 -1
  78. package/dist/sheets/providers/google-sheets-api/operations/rowChecks.d.ts.map +1 -1
  79. package/dist/sheets/providers/google-sheets-api/operations/rowChecks.js +9 -7
  80. package/dist/sheets/providers/google-sheets-api/operations/rowChecks.js.map +1 -1
  81. package/dist/sheets/providers/google-sheets-api/operations/shared.d.ts +119 -58
  82. package/dist/sheets/providers/google-sheets-api/operations/shared.d.ts.map +1 -1
  83. package/dist/sheets/providers/google-sheets-api/operations/shared.js +168 -153
  84. package/dist/sheets/providers/google-sheets-api/operations/shared.js.map +1 -1
  85. package/dist/sheets/providers/google-sheets-api/transport/googleSheetsApiTransport.d.ts +1 -1
  86. package/dist/sheets/providers/google-sheets-api/transport/googleSheetsApiTransport.js +4 -4
  87. package/dist/sheets/providers/google-sheets-api/transport/googleSheetsApiTransport.js.map +1 -1
  88. package/dist/storage/sqlite/migrateSchema.d.ts.map +1 -1
  89. package/dist/storage/sqlite/migrateSchema.js +36 -3
  90. package/dist/storage/sqlite/migrateSchema.js.map +1 -1
  91. package/dist/storage/sqlite/schema.d.ts +3 -1
  92. package/dist/storage/sqlite/schema.d.ts.map +1 -1
  93. package/dist/storage/sqlite/schema.js +6 -2
  94. package/dist/storage/sqlite/schema.js.map +1 -1
  95. package/dist/storage/sqlite/schemaTypes.d.ts +1 -1
  96. package/dist/storage/sqlite/schemaTypes.d.ts.map +1 -1
  97. package/dist/sync/outbound/projection/ProjectionEffectFactory.d.ts +19 -0
  98. package/dist/sync/outbound/projection/ProjectionEffectFactory.d.ts.map +1 -1
  99. package/dist/sync/outbound/projection/ProjectionEffectFactory.js +35 -0
  100. package/dist/sync/outbound/projection/ProjectionEffectFactory.js.map +1 -1
  101. package/dist/sync-engine/api/hikouteiCore.js +2 -2
  102. package/dist/sync-engine/api/hikouteiCore.js.map +1 -1
  103. package/dist/sync-engine/api/internalEntityManager.js +2 -2
  104. package/dist/sync-engine/api/internalEntityManager.js.map +1 -1
  105. package/dist/sync-engine/sync/outbound/SheetsEffectDispatcher.d.ts +13 -2
  106. package/dist/sync-engine/sync/outbound/SheetsEffectDispatcher.d.ts.map +1 -1
  107. package/dist/sync-engine/sync/outbound/SheetsEffectDispatcher.js +37 -5
  108. package/dist/sync-engine/sync/outbound/SheetsEffectDispatcher.js.map +1 -1
  109. package/dist/sync-engine/sync/outbound/dispatcherSupport.d.ts +4 -7
  110. package/dist/sync-engine/sync/outbound/dispatcherSupport.d.ts.map +1 -1
  111. package/dist/sync-engine/sync/outbound/dispatcherSupport.js +4 -14
  112. package/dist/sync-engine/sync/outbound/dispatcherSupport.js.map +1 -1
  113. package/dist/sync-engine/sync/service/SyncServiceBootstrap.js +2 -2
  114. package/dist/sync-engine/sync/service/SyncServiceBootstrap.js.map +1 -1
  115. package/dist/sync-engine/sync/service/adopt/adoptionSeeding.js +1 -1
  116. package/dist/sync-engine/sync/service/adopt/adoptionSeeding.js.map +1 -1
  117. package/dist/sync-engine/sync/service/effectSupervisor.js +2 -2
  118. package/dist/sync-engine/sync/service/effectSupervisor.js.map +1 -1
  119. package/dist/sync-engine/sync/service/pollingSupervisor.js +2 -2
  120. package/dist/sync-engine/sync/service/pollingSupervisor.js.map +1 -1
  121. package/dist/sync-engine/sync/service/requestTelemetry.js +2 -2
  122. package/dist/sync-engine/sync/service/requestTelemetry.js.map +1 -1
  123. package/dist/sync-engine/sync/service/shutdown.js +1 -1
  124. package/dist/sync-engine/sync/service/shutdown.js.map +1 -1
  125. package/dist/sync-engine/sync/service/syncAutoStart.js +2 -2
  126. package/dist/sync-engine/sync/service/syncAutoStart.js.map +1 -1
  127. package/dist/sync-engine/sync/sheetsContract/conflictProjectionRegistration.js +1 -1
  128. package/dist/sync-engine/sync/sheetsContract/conflictProjectionRegistration.js.map +1 -1
  129. package/package.json +2 -2
  130. package/dist/contracts/sheets/transportOutcome.d.ts +0 -90
  131. package/dist/contracts/sheets/transportOutcome.d.ts.map +0 -1
  132. package/dist/contracts/sheets/transportOutcome.js +0 -191
  133. package/dist/contracts/sheets/transportOutcome.js.map +0 -1
  134. package/dist/sheets/providers/google-sheets-api/model/readPlan.d.ts +0 -168
  135. package/dist/sheets/providers/google-sheets-api/model/readPlan.d.ts.map +0 -1
  136. package/dist/sheets/providers/google-sheets-api/model/readPlan.js +0 -184
  137. package/dist/sheets/providers/google-sheets-api/model/readPlan.js.map +0 -1
  138. package/dist/sheets/providers/google-sheets-api/model/receiptCursor.d.ts +0 -102
  139. package/dist/sheets/providers/google-sheets-api/model/receiptCursor.d.ts.map +0 -1
  140. package/dist/sheets/providers/google-sheets-api/model/receiptCursor.js +0 -132
  141. package/dist/sheets/providers/google-sheets-api/model/receiptCursor.js.map +0 -1
  142. package/dist/sheets/providers/google-sheets-api/model/rowCheckFormula.d.ts +0 -35
  143. package/dist/sheets/providers/google-sheets-api/model/rowCheckFormula.d.ts.map +0 -1
  144. package/dist/sheets/providers/google-sheets-api/model/rowCheckFormula.js +0 -57
  145. package/dist/sheets/providers/google-sheets-api/model/rowCheckFormula.js.map +0 -1
  146. package/dist/sheets/providers/google-sheets-api/model/sheetIdAllocator.d.ts +0 -16
  147. package/dist/sheets/providers/google-sheets-api/model/sheetIdAllocator.d.ts.map +0 -1
  148. package/dist/sheets/providers/google-sheets-api/model/sheetIdAllocator.js +0 -29
  149. package/dist/sheets/providers/google-sheets-api/model/sheetIdAllocator.js.map +0 -1
  150. package/dist/sheets/providers/google-sheets-api/operations/readEngine.d.ts +0 -50
  151. package/dist/sheets/providers/google-sheets-api/operations/readEngine.d.ts.map +0 -1
  152. package/dist/sheets/providers/google-sheets-api/operations/readEngine.js +0 -124
  153. package/dist/sheets/providers/google-sheets-api/operations/readEngine.js.map +0 -1
  154. package/dist/sheets/providers/google-sheets-api/operations/writeEngine.d.ts +0 -90
  155. package/dist/sheets/providers/google-sheets-api/operations/writeEngine.d.ts.map +0 -1
  156. package/dist/sheets/providers/google-sheets-api/operations/writeEngine.js +0 -112
  157. package/dist/sheets/providers/google-sheets-api/operations/writeEngine.js.map +0 -1
  158. package/dist/sheets/providers/google-sheets-api/transport/quotaGovernor.d.ts +0 -229
  159. package/dist/sheets/providers/google-sheets-api/transport/quotaGovernor.d.ts.map +0 -1
  160. package/dist/sheets/providers/google-sheets-api/transport/quotaGovernor.js +0 -299
  161. package/dist/sheets/providers/google-sheets-api/transport/quotaGovernor.js.map +0 -1
  162. package/dist/sheets/providers/google-sheets-api/transport/rateLimiter.d.ts +0 -185
  163. package/dist/sheets/providers/google-sheets-api/transport/rateLimiter.d.ts.map +0 -1
  164. package/dist/sheets/providers/google-sheets-api/transport/rateLimiter.js +0 -248
  165. package/dist/sheets/providers/google-sheets-api/transport/rateLimiter.js.map +0 -1
  166. package/dist/sheets/providers/google-sheets-api/transport/rawErrorSchemas.d.ts +0 -7
  167. package/dist/sheets/providers/google-sheets-api/transport/rawErrorSchemas.d.ts.map +0 -1
  168. package/dist/sheets/providers/google-sheets-api/transport/rawErrorSchemas.js +0 -26
  169. package/dist/sheets/providers/google-sheets-api/transport/rawErrorSchemas.js.map +0 -1
  170. package/dist/sync-engine/shared/observability/internalLog.d.ts.map +0 -1
  171. package/dist/sync-engine/shared/observability/internalLog.js.map +0 -1
  172. package/dist/sync-engine/shared/observability/logEvents.d.ts.map +0 -1
  173. package/dist/sync-engine/shared/observability/logEvents.js.map +0 -1
  174. /package/dist/{sync-engine → contracts}/shared/observability/internalLog.d.ts +0 -0
  175. /package/dist/{sync-engine → contracts}/shared/observability/internalLog.js +0 -0
  176. /package/dist/{sync-engine → contracts}/shared/observability/logEvents.d.ts +0 -0
  177. /package/dist/{sync-engine → contracts}/shared/observability/logEvents.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"readEngine.d.ts","sourceRoot":"","sources":["../../../../../../../../src/sheets/providers/google-sheets-api/operations/readEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EAEb,YAAY,EACb,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAIL,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACxB,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,2BAA2B,EACjC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,GACZ,SAAS,CAwDX;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,2BAA2B,EACjC,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,MAAM,GACZ,aAAa,CAMf;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,2BAA2B,EACjC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -1,124 +0,0 @@
1
- /**
2
- * Unified read engine executor (design/unified-read-engine.md §3).
3
- *
4
- * Runs an already-packed band plan as SEQUENTIAL paced `spreadsheets.get`
5
- * requests on the lane's request-start class and reassembles the replies
6
- * into one logical document: every requested range's GridData in request
7
- * order, concatenated per sheet id, so lanes consume band replies through
8
- * the SAME accessors (`resolveGridCell`, `synthesizeScopedTargetGrid`,
9
- * `pickRegisteredGrid`) that serve today's multi-range replies. Each band
10
- * is one server snapshot and consumes exactly one `runRead` slot, so:
11
- * - telemetry emits ONE event per band with the RAW-document `responseBytes`
12
- * (sink-gated exactly like the historical reads) — per-lane, per-band
13
- * bytes are observable without any extra plumbing;
14
- * - a timeout or rejection fails ONE band with the existing
15
- * delivery-uncertain classification instead of an all-or-nothing
16
- * multi-megabyte single request;
17
- * - every response's `sheets.properties.gridProperties.rowCount` refreshes
18
- * the provider-instance authoritative bounds cache (a ranged GET returns
19
- * properties for the intersecting sheets), and `responseBytes ÷
20
- * cellsRequested` feeds the per-evidence calibration multiplier, so a
21
- * mispredicted band size shrinks the NEXT pass's bands.
22
- */
23
- import { enumerateSheetProperties } from "../model/preflightContext.js";
24
- import { parseSpreadsheetDocument } from "../model/preflightParsing.js";
25
- import { createRawResponseMeta, credentialBinding, runRead, } from "./shared.js";
26
- /**
27
- * Builds the executor for ONE logical read: fixed field mask, evidence
28
- * class, pacing lane, and telemetry label. The returned closure owns no
29
- * state — bounds/calibration updates land on the shared `deps` carriers.
30
- */
31
- export function createBandedGet(deps, pacing, fields, evidence, label) {
32
- return async (requests) => {
33
- const sheetsByTitle = new Map();
34
- const grids = new Map();
35
- let executed = 0;
36
- let bytes = 0;
37
- for (const request of requests) {
38
- if (request.length === 0)
39
- continue;
40
- const ranges = request.map((item) => item.range);
41
- const cells = request.reduce((total, item) => total + item.cells, 0);
42
- // The RAW document is measured INSIDE the paced task (the awaited-call
43
- // ordering the historical reads proved): runRead emits its telemetry
44
- // event when the task resolves, so a later measurement would land one
45
- // event too late.
46
- const rawMeta = createRawResponseMeta(deps);
47
- const raw = await runRead(deps, async (credentialIndex) => {
48
- const response = await deps.transport.getSpreadsheet({
49
- spreadsheetId: deps.spreadsheetId,
50
- ranges,
51
- fields,
52
- ...(deps.readTimeoutMs === undefined ? {} : { timeoutMs: deps.readTimeoutMs }),
53
- ...credentialBinding(credentialIndex),
54
- });
55
- rawMeta.onRawResponse?.(response);
56
- return response;
57
- }, pacing, rawMeta.meta);
58
- executed += 1;
59
- const document = parseSpreadsheetDocument(raw, label);
60
- for (const sheet of document.sheets) {
61
- // Last-seen properties win (fresher grid metadata); consumers only
62
- // read identity/merges from this list, grid data lives in `grids`.
63
- sheetsByTitle.set(sheet.title, sheet);
64
- const rowCount = sheet.gridProperties?.rowCount;
65
- if (rowCount !== undefined)
66
- deps.sheetRowBounds.set(sheet.title, rowCount);
67
- }
68
- for (const [sheetId, list] of document.grids) {
69
- const existing = grids.get(sheetId);
70
- if (existing === undefined)
71
- grids.set(sheetId, [...list]);
72
- else
73
- existing.push(...list);
74
- }
75
- if (rawMeta.meta.responseBytes !== undefined) {
76
- bytes += rawMeta.meta.responseBytes;
77
- deps.readCalibration.observe(evidence, cells, rawMeta.meta.responseBytes);
78
- }
79
- }
80
- const document = {
81
- sheets: [...sheetsByTitle.values()],
82
- grids,
83
- requests: executed,
84
- bytes,
85
- };
86
- return document;
87
- };
88
- }
89
- /**
90
- * Builds the model-facing engine runtime for one logical read on one lane:
91
- * the fields/evidence → executor factory plus the shared bounds cache and
92
- * calibration tracker. Model functions receive this instead of a raw
93
- * transport, which is what lets a single logical read expand into
94
- * sequential paced band requests WITHOUT the model layer importing the
95
- * operations layer.
96
- */
97
- export function createEngineRuntime(deps, pacing, label) {
98
- return {
99
- makeGet: (fields, evidence) => createBandedGet(deps, pacing, fields, evidence, label),
100
- rowBounds: deps.sheetRowBounds,
101
- calibration: deps.readCalibration,
102
- };
103
- }
104
- /**
105
- * Ensures every listed tab has an authoritative row bound in the
106
- * provider-instance cache, settling cold titles with ONE range-less
107
- * metadata enumeration (`gridProperties.rowCount` is metadata-only). The
108
- * cache is refreshed by every subsequent engine response's sheet
109
- * properties, so the enumeration is a once-per-title-per-instance cost —
110
- * the polling lane has no per-dispatch enumeration of its own and this is
111
- * where its committed upper bound comes from.
112
- */
113
- export async function ensureSheetRowBounds(deps, pacing, titles) {
114
- if (titles.every((title) => deps.sheetRowBounds.has(title)))
115
- return;
116
- const enumeration = createRawResponseMeta(deps);
117
- const sheets = await runRead(deps, (credentialIndex) => enumerateSheetProperties(deps.transport, deps.spreadsheetId, deps.readTimeoutMs, enumeration.onRawResponse, credentialIndex), pacing, enumeration.meta);
118
- for (const sheet of sheets) {
119
- const rowCount = sheet.gridProperties?.rowCount;
120
- if (rowCount !== undefined)
121
- deps.sheetRowBounds.set(sheet.title, rowCount);
122
- }
123
- }
124
- //# sourceMappingURL=readEngine.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"readEngine.js","sourceRoot":"","sources":["../../../../../../../../src/sheets/providers/google-sheets-api/operations/readEngine.ts"],"names":[],"mappings":"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"}
@@ -1,90 +0,0 @@
1
- /**
2
- * Unified write engine executor (mirrors the read side's `readEngine.ts`).
3
- *
4
- * Every provider write path (fast-append single/multi, apply target + inline
5
- * receipt follow-up, combined multi-route apply) runs the SAME mechanics:
6
- * build the batch (model/batchBuilder), pace one `batchUpdate` start on the
7
- * WRITE limiter (`runWrite`), and validate the reply
8
- * (`requireValidBatchUpdateReply`) so a malformed 2xx never closes effects.
9
- * `executeBatchUpdate` is the single implementation of that sequence; the
10
- * builders and the post-write result encoding stay with the callers because
11
- * their contents and bookkeeping differ per operation.
12
- *
13
- * `executePreparedWrite` is the single implementation of the receipt-tab
14
- * initialization guard: a read-ahead preflight can observe the shared receipt
15
- * tab absent before a concurrent write creates it, and two stale preflights
16
- * would otherwise both emit a duplicate `addSheet` (the second fails 400).
17
- * When the unit needs initialization, refresh + write run as ONE atomic
18
- * section on the per-spreadsheet `receiptInitLock`; steady state (receipt
19
- * present at preflight) never takes the lock. Callers keep their own
20
- * eligibility guard: a deterministic no-op batch must not take the refresh,
21
- * whose write-lane admission can be refused under saturation and would turn
22
- * the no-op into a delivery-uncertain requeue.
23
- *
24
- * `groupByRouteKey` is the single implementation of multi-route grouping:
25
- * items are bucketed by their canonical route key, first-seen group order and
26
- * per-group order preserved (the grouped plan order drives the combined byte
27
- * budget and the result walk, so both must stay stable).
28
- */
29
- import type { BuiltApplyBatch } from "../model/batchBuilder.js";
30
- import type { PreflightContext } from "../model/preflightContext.js";
31
- import { type GoogleSheetsApiProviderDeps } from "./shared.js";
32
- /** Per-operation effect counts attached to one write event's telemetry. */
33
- export interface WriteBatchTelemetry {
34
- /** Effects requested for the whole operation (pre-budget). */
35
- readonly requestedEffects: number;
36
- /** Effects included in the written batch (the budget-fitting prefix). */
37
- readonly includedEffects: number;
38
- }
39
- /**
40
- * Sends one built batch as ONE paced `batchUpdate` and validates the reply.
41
- *
42
- * `BuiltApplyBatch` is the shared return shape of every batch builder (apply,
43
- * append, and their combined variants), and the batch contents here are
44
- * exactly what the caller's builder produced: the engine never rebuilds or
45
- * reorders requests. A malformed or short reply throws the existing
46
- * delivery-uncertain invalid-state classification, so a 2xx that cannot be
47
- * matched request-for-request never closes effects. Zero-request batches must
48
- * be skipped by the caller (no transport call and no telemetry event for an
49
- * empty batch, exactly like before).
50
- */
51
- export declare function executeBatchUpdate(deps: GoogleSheetsApiProviderDeps, batch: BuiltApplyBatch, telemetry: WriteBatchTelemetry): Promise<void>;
52
- /**
53
- * Runs one prepared write unit behind the receipt-init guard.
54
- *
55
- * `context` is whatever the write closure needs (a single route's
56
- * `PreflightContext` or a multi-route list). When `needsReceiptInit` is true,
57
- * `refresh` re-reads the shared receipt tab under the `receiptInitLock` and
58
- * `write` runs against the REFRESHED context inside the same lock section;
59
- * otherwise `write` runs against the preflight context with no lock. Failure
60
- * behavior is unchanged: a refused refresh admission or a rejected write
61
- * propagates with its own classification, and the tail lock still releases
62
- * for the next holder.
63
- */
64
- export declare function executePreparedWrite<C, R>(deps: GoogleSheetsApiProviderDeps, unit: {
65
- readonly context: C;
66
- readonly needsReceiptInit: boolean;
67
- readonly refresh: (context: C) => Promise<C>;
68
- readonly write: (context: C) => Promise<R>;
69
- }): Promise<R>;
70
- /**
71
- * Refreshes the shared receipt tab through the FIRST route's context and
72
- * returns the route list with that context replaced (multi-route units).
73
- *
74
- * Provisioning guarantees one definition per tab, so every route of one
75
- * combined batch sees the SAME receipt-tab presence at preflight; refreshing
76
- * the first context is sufficient and later writers append instead of
77
- * re-emitting `addSheet`. An empty route list is returned unchanged (nothing
78
- * to refresh or write).
79
- */
80
- export declare function refreshFirstRouteContext<R extends {
81
- readonly context: PreflightContext;
82
- }>(deps: GoogleSheetsApiProviderDeps, routes: readonly R[]): Promise<readonly R[]>;
83
- /** True when a preflight context observed the shared receipt tab absent. */
84
- export declare function receiptInitNeeded(context: PreflightContext): boolean;
85
- /**
86
- * Buckets items by their canonical route key (see `routeKeyOf` in
87
- * applyEffects): first-seen group order and per-group order are preserved.
88
- */
89
- export declare function groupByRouteKey<T>(items: readonly T[], keyOf: (item: T) => string): readonly (readonly T[])[];
90
- //# sourceMappingURL=writeEngine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writeEngine.d.ts","sourceRoot":"","sources":["../../../../../../../../src/sheets/providers/google-sheets-api/operations/writeEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAIL,KAAK,2BAA2B,EACjC,MAAM,aAAa,CAAC;AAErB,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,yEAAyE;IACzE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,2BAA2B,EACjC,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAC7C,IAAI,EAAE,2BAA2B,EACjC,IAAI,EAAE;IACJ,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CAC5C,GACA,OAAO,CAAC,CAAC,CAAC,CAIZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,CAAC,SAAS;IAAE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,EAEhD,IAAI,EAAE,2BAA2B,EACjC,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAMvB;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAEpE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GACzB,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAY3B"}
@@ -1,112 +0,0 @@
1
- /**
2
- * Unified write engine executor (mirrors the read side's `readEngine.ts`).
3
- *
4
- * Every provider write path (fast-append single/multi, apply target + inline
5
- * receipt follow-up, combined multi-route apply) runs the SAME mechanics:
6
- * build the batch (model/batchBuilder), pace one `batchUpdate` start on the
7
- * WRITE limiter (`runWrite`), and validate the reply
8
- * (`requireValidBatchUpdateReply`) so a malformed 2xx never closes effects.
9
- * `executeBatchUpdate` is the single implementation of that sequence; the
10
- * builders and the post-write result encoding stay with the callers because
11
- * their contents and bookkeeping differ per operation.
12
- *
13
- * `executePreparedWrite` is the single implementation of the receipt-tab
14
- * initialization guard: a read-ahead preflight can observe the shared receipt
15
- * tab absent before a concurrent write creates it, and two stale preflights
16
- * would otherwise both emit a duplicate `addSheet` (the second fails 400).
17
- * When the unit needs initialization, refresh + write run as ONE atomic
18
- * section on the per-spreadsheet `receiptInitLock`; steady state (receipt
19
- * present at preflight) never takes the lock. Callers keep their own
20
- * eligibility guard: a deterministic no-op batch must not take the refresh,
21
- * whose write-lane admission can be refused under saturation and would turn
22
- * the no-op into a delivery-uncertain requeue.
23
- *
24
- * `groupByRouteKey` is the single implementation of multi-route grouping:
25
- * items are bucketed by their canonical route key, first-seen group order and
26
- * per-group order preserved (the grouped plan order drives the combined byte
27
- * budget and the result walk, so both must stay stable).
28
- */
29
- import { PRESENCE_KINDS } from "../../../../contracts/state/index.js";
30
- import { refreshReceiptForWrite } from "./preflightOp.js";
31
- import { credentialBinding, requireValidBatchUpdateReply, runWrite, } from "./shared.js";
32
- /**
33
- * Sends one built batch as ONE paced `batchUpdate` and validates the reply.
34
- *
35
- * `BuiltApplyBatch` is the shared return shape of every batch builder (apply,
36
- * append, and their combined variants), and the batch contents here are
37
- * exactly what the caller's builder produced: the engine never rebuilds or
38
- * reorders requests. A malformed or short reply throws the existing
39
- * delivery-uncertain invalid-state classification, so a 2xx that cannot be
40
- * matched request-for-request never closes effects. Zero-request batches must
41
- * be skipped by the caller (no transport call and no telemetry event for an
42
- * empty batch, exactly like before).
43
- */
44
- export async function executeBatchUpdate(deps, batch, telemetry) {
45
- const response = await runWrite(deps, (credentialIndex) => deps.transport.batchUpdate({
46
- spreadsheetId: deps.spreadsheetId,
47
- requests: batch.requests,
48
- ...credentialBinding(credentialIndex),
49
- }), {
50
- requestCount: batch.requests.length,
51
- bodyBytes: batch.bytes,
52
- ...telemetry,
53
- });
54
- requireValidBatchUpdateReply(response, batch.requests.length);
55
- }
56
- /**
57
- * Runs one prepared write unit behind the receipt-init guard.
58
- *
59
- * `context` is whatever the write closure needs (a single route's
60
- * `PreflightContext` or a multi-route list). When `needsReceiptInit` is true,
61
- * `refresh` re-reads the shared receipt tab under the `receiptInitLock` and
62
- * `write` runs against the REFRESHED context inside the same lock section;
63
- * otherwise `write` runs against the preflight context with no lock. Failure
64
- * behavior is unchanged: a refused refresh admission or a rejected write
65
- * propagates with its own classification, and the tail lock still releases
66
- * for the next holder.
67
- */
68
- export async function executePreparedWrite(deps, unit) {
69
- if (!unit.needsReceiptInit)
70
- return unit.write(unit.context);
71
- return deps.receiptInitLock.run(async () => unit.write(await unit.refresh(unit.context)));
72
- }
73
- /**
74
- * Refreshes the shared receipt tab through the FIRST route's context and
75
- * returns the route list with that context replaced (multi-route units).
76
- *
77
- * Provisioning guarantees one definition per tab, so every route of one
78
- * combined batch sees the SAME receipt-tab presence at preflight; refreshing
79
- * the first context is sufficient and later writers append instead of
80
- * re-emitting `addSheet`. An empty route list is returned unchanged (nothing
81
- * to refresh or write).
82
- */
83
- export async function refreshFirstRouteContext(deps, routes) {
84
- const first = routes[0];
85
- if (first === undefined)
86
- return routes;
87
- const refreshed = await refreshReceiptForWrite(deps, first.context);
88
- return routes.map((route, index) => index === 0 ? { ...route, context: refreshed } : route);
89
- }
90
- /** True when a preflight context observed the shared receipt tab absent. */
91
- export function receiptInitNeeded(context) {
92
- return context.receiptSheetId.kind === PRESENCE_KINDS.ABSENT;
93
- }
94
- /**
95
- * Buckets items by their canonical route key (see `routeKeyOf` in
96
- * applyEffects): first-seen group order and per-group order are preserved.
97
- */
98
- export function groupByRouteKey(items, keyOf) {
99
- const groups = new Map();
100
- for (const item of items) {
101
- const key = keyOf(item);
102
- const group = groups.get(key);
103
- if (group === undefined) {
104
- groups.set(key, [item]);
105
- }
106
- else {
107
- group.push(item);
108
- }
109
- }
110
- return [...groups.values()];
111
- }
112
- //# sourceMappingURL=writeEngine.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writeEngine.js","sourceRoot":"","sources":["../../../../../../../../src/sheets/providers/google-sheets-api/operations/writeEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,QAAQ,GAET,MAAM,aAAa,CAAC;AAUrB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAiC,EACjC,KAAsB,EACtB,SAA8B;IAE9B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,eAAe,EAAE,EAAE,CACxD,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;QACzB,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,GAAG,iBAAiB,CAAC,eAAe,CAAC;KACtC,CAAC,EAAE;QACJ,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;QACnC,SAAS,EAAE,KAAK,CAAC,KAAK;QACtB,GAAG,SAAS;KACb,CAAC,CAAC;IACH,4BAA4B,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAiC,EACjC,IAKC;IAED,IAAI,CAAC,IAAI,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CACzC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAG5C,IAAiC,EACjC,MAAoB;IAEpB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACjC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,iBAAiB,CAAC,OAAyB;IACzD,OAAO,OAAO,CAAC,cAAc,CAAC,IAAI,KAAK,cAAc,CAAC,MAAM,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAmB,EACnB,KAA0B;IAE1B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAe,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AAC9B,CAAC"}
@@ -1,229 +0,0 @@
1
- /**
2
- * Adaptive quota governor layered ON TOP of the request-start limiters.
3
- *
4
- * The interval limiters (`RequestStartLimiter`, `ReadQoSScheduler`) space
5
- * request STARTS but have no notion of the per-minute quota budget, and a
6
- * remote 429 never feeds back into their pacing. This module adds the two
7
- * missing pieces, both of which gate request STARTS only and never touch
8
- * CAS/fencing, prepared-state, batch building, or result encoding:
9
- *
10
- * 1. `RollingQuotaBudget` — a sliding-window per-minute TOTAL request-start
11
- * budget per lane (reads vs writes). It composes with (does not replace)
12
- * the interval limiters: a start must pass BOTH the budget and its lane's
13
- * interval pacing. Admission is BOUNDED with the same semantics as the
14
- * interval limiters: a refused caller reserves nothing, so a refusal can
15
- * never advance the budget window or the pacing horizon.
16
- *
17
- * 2. `QuotaPacingGovernor` — AIMD pacing feedback. When a transport response
18
- * is classified as quota-limited (HTTP 429 / `RESOURCE_EXHAUSTED`), the
19
- * offending lane's pacing interval doubles (multiplicative decrease,
20
- * capped at a multiple of the base). After a sustained quiet period
21
- * (enough successful request starts, or enough elapsed time since the
22
- * last quota event), the interval steps back down ~10% at a time
23
- * (additive increase) and never falls below the base. With no 429 ever
24
- * observed the governor stays `nominal` at 1x and pacing is byte-for-byte
25
- * the pre-governor behavior.
26
- *
27
- * Why a per-minute budget at all: the binding Google quota for our
28
- * deployment is the per-user READ rate (60/min); a measured 30k-effect
29
- * burst peaked near 69/min of reads, producing 429s and a delivery-uncertain
30
- * requeue spiral. The interval pacing alone (75/min at the 800 ms default)
31
- * cannot hold a per-minute ceiling because concurrent lock-free readers each
32
- * reserve successive interval slots without any rate cap per window.
33
- */
34
- import { type Presence } from "../../../../contracts/state/index.js";
35
- /** Lanes the governor paces: the shared read timeline and the write lane. */
36
- export declare const QUOTA_GOVERNOR_LANES: {
37
- readonly READ: "read";
38
- readonly WRITE: "write";
39
- };
40
- /** Union type derived from the governor lane table. */
41
- export type QuotaGovernorLane = (typeof QUOTA_GOVERNOR_LANES)[keyof typeof QUOTA_GOVERNOR_LANES];
42
- /** Lifecycle states of one lane's AIMD pacing. */
43
- export declare const QUOTA_PACING_STATES: {
44
- readonly NOMINAL: "nominal";
45
- readonly BACKOFF: "backoff";
46
- readonly RECOVERY: "recovery";
47
- };
48
- /**
49
- * Discriminated AIMD pacing state of ONE lane.
50
- *
51
- * `nominal` — never backed off (or fully recovered); multiplier is exactly 1.
52
- * `backoff` — at least one quota event, no recovery step taken yet.
53
- * `recovery` — at least one recovery step taken, still above the base.
54
- * The state carries the counters the next transition reads; there is no
55
- * sentinel `null` for "not backed off" — `nominal` is its own variant.
56
- */
57
- export type QuotaPacingState = {
58
- readonly status: typeof QUOTA_PACING_STATES.NOMINAL;
59
- readonly multiplier: 1;
60
- } | {
61
- readonly status: typeof QUOTA_PACING_STATES.BACKOFF;
62
- readonly multiplier: number;
63
- /** Clock instant of the most recent quota-limited response. */
64
- readonly lastQuotaEventAt: number;
65
- /** Successful request starts recorded since that event. */
66
- readonly quietStarts: number;
67
- } | {
68
- readonly status: typeof QUOTA_PACING_STATES.RECOVERY;
69
- readonly multiplier: number;
70
- readonly lastQuotaEventAt: number;
71
- readonly quietStarts: number;
72
- };
73
- export interface QuotaPacingGovernorOptions {
74
- /** Configured base pacing interval for both lanes. */
75
- readonly baseIntervalMs: number;
76
- /** Injectable clock for deterministic tests; defaults to Date.now. */
77
- readonly now?: () => number;
78
- }
79
- /**
80
- * AIMD pacing feedback for the two request-start lanes.
81
- *
82
- * `intervalMsFor(lane)` is polled by the lane's limiter at each reservation,
83
- * so a doubled multiplier doubles the effective spacing on the NEXT start
84
- * without reconstructing the limiter. `recordRequestStart` and
85
- * `recordQuotaLimited` are the only state inputs; both are fire-and-forget
86
- * bookkeeping that can never throw out of the admission path.
87
- */
88
- export declare class QuotaPacingGovernor {
89
- private readonly baseIntervalMs;
90
- private readonly now;
91
- private readonly lanes;
92
- constructor(options: QuotaPacingGovernorOptions);
93
- /** Effective pacing interval for one lane: base x AIMD multiplier. */
94
- intervalMsFor(lane: QuotaGovernorLane): number;
95
- /**
96
- * Multiplicative decrease: one quota-limited (429) response doubles this
97
- * lane's multiplier, capped at `QUOTA_BACKOFF_MAX_MULTIPLIER` of base.
98
- */
99
- recordQuotaLimited(lane: QuotaGovernorLane): void;
100
- /**
101
- * Additive increase: one successful request start on this lane. After a
102
- * sustained quiet period (RECOVERY_SUCCESS_THRESHOLD starts, or
103
- * RECOVERY_QUIET_MS elapsed since the last quota event) the multiplier
104
- * steps down by ~10% and needs a FRESH quiet period before the next step,
105
- * so recovery is gradual and a single 429 cannot be answered with a
106
- * immediate undo. Landing on exactly 1x returns the lane to `nominal`.
107
- */
108
- recordRequestStart(lane: QuotaGovernorLane): void;
109
- /**
110
- * Elapsed-time-only quiet recovery, applied lazily at every state
111
- * observation: with no traffic on the lane, `recordRequestStart` never
112
- * runs, so a backed-off lane would otherwise stay in backoff forever.
113
- */
114
- private recoverByElapsed;
115
- /** One additive-increase step: ~10% down, clamped at nominal (1x). */
116
- private stepDown;
117
- /** Read-only snapshot of one lane's pacing state (for telemetry/tests). */
118
- stateFor(lane: QuotaGovernorLane): QuotaPacingState;
119
- }
120
- /**
121
- * Returns true when a classified transport outcome proves the request was
122
- * quota-limited remotely (HTTP 429 or the allowlisted `RESOURCE_EXHAUSTED`
123
- * google.rpc code; either marker alone is sufficient because a proxy-emitted
124
- * 429 can carry no body and a body can omit the status line evidence).
125
- */
126
- export declare function isQuotaLimitedOutcome(outcome: {
127
- readonly httpStatus: Presence<number>;
128
- readonly code: Presence<string>;
129
- }): boolean;
130
- export interface RollingQuotaBudgetOptions {
131
- /**
132
- * Maximum admitted request starts per window for this lane.
133
- * `Number.POSITIVE_INFINITY` disables the budget (used by tests that pin
134
- * pacing separately and simulate high rates over near-zero wall time).
135
- */
136
- readonly maxStartsPerWindow: number;
137
- /** Sliding window length in ms (Google quotas are per-minute). */
138
- readonly windowMs: number;
139
- /** Injectable clock for deterministic tests; defaults to Date.now. */
140
- readonly now?: () => number;
141
- /** Injectable sleep used while waiting for the next budget slot. */
142
- readonly sleep?: (ms: number) => Promise<void>;
143
- }
144
- /**
145
- * Opaque handle for ONE provisional budget reservation returned by
146
- * `waitForSlot`. Passed back to {@link RollingQuotaBudget.rollback} when a
147
- * downstream admission gate refuses after the budget already reserved, so a
148
- * refused request never keeps consuming budget. The token is matched by
149
- * OBJECT IDENTITY, never by its timestamp, so a rollback can never release
150
- * a different (live) reservation, and a repeated rollback is a no-op.
151
- */
152
- export interface BudgetReservation {
153
- /** Internal: the reserved start time, read only by the owning budget. */
154
- readonly reservedAt: number;
155
- }
156
- /** Admitted result of `RollingQuotaBudget.waitForSlot` (adds the rollback token). */
157
- export type RollingQuotaBudgetAdmission = {
158
- readonly status: "admitted";
159
- readonly waitedMs: number;
160
- readonly reservation: BudgetReservation;
161
- } | {
162
- readonly status: "refused";
163
- readonly waitedMs: number;
164
- readonly nextStartAt: number;
165
- };
166
- /**
167
- * Sliding-window per-minute request-start budget for ONE lane.
168
- *
169
- * Reservations, not completed requests, occupy the window: an admitted
170
- * caller records the slot it will start at, so a burst of concurrent
171
- * callers arriving in the same tick each consumes one of the remaining
172
- * budget slots and the deep ones are refused by the bounded wait, exactly
173
- * like the interval limiters. A budget refusal records NOTHING, so the
174
- * window can never be poisoned forward by refused callers.
175
- *
176
- * A budget ADMISSION reserves provisionally: a caller that later has to
177
- * refuse on a downstream gate (e.g. the pacing lane) hands the reservation
178
- * token to `rollback`, which removes exactly that entry. Rollback never
179
- * advances (or otherwise touches) the window and can never free a live
180
- * reservation belonging to another caller.
181
- *
182
- * The earliest legal start when the window already holds `max` reservations
183
- * is `starts[n - max] + windowMs`: at that instant all but the `max - 1`
184
- * newest reservations have aged out, so admitting keeps the count at `max`.
185
- */
186
- export declare class RollingQuotaBudget {
187
- private readonly maxStartsPerWindow;
188
- private readonly windowMs;
189
- private readonly now;
190
- private readonly sleep;
191
- /**
192
- * Reserved start times, kept in chronological (non-decreasing `reservedAt`)
193
- * order at all times. Rollback splices its own entry out (order survives)
194
- * and every new reservation is inserted at its sorted position rather than
195
- * blindly appended: a rolled-back older slot must never let a later caller
196
- * land BEHIND a queued future reservation, or the prefix expiry scan would
197
- * stop at the future entry and retain the trailing expired one forever,
198
- * leaking budget capacity.
199
- */
200
- private starts;
201
- constructor(options: RollingQuotaBudgetOptions);
202
- /** Number of reservations (admitted, possibly still sleeping) in window. */
203
- reservedCount(): number;
204
- /**
205
- * Bounded admission to one budget slot: waits only when the predicted
206
- * slot is at most `maxWaitMs` out, otherwise returns `refused` having
207
- * reserved nothing. The decision and the reservation happen synchronously
208
- * before any await, so concurrent callers can never double-book one slot.
209
- */
210
- waitForSlot(maxWaitMs: number): Promise<RollingQuotaBudgetAdmission>;
211
- /**
212
- * Inserts one reservation keeping {@link starts} chronologically ordered.
213
- * The common case (slot at or after every existing entry) is a plain push;
214
- * only an out-of-order arrival after a rollback walks back from the tail,
215
- * which is bounded by the window budget (a few hundred entries per minute).
216
- */
217
- private insertReservation;
218
- /**
219
- * Rolls back one PROVISIONAL budget reservation returned by `waitForSlot`
220
- * whose caller never reached request start (e.g. a downstream pacing-lane
221
- * refusal). Invariants: the removal is matched by object identity, so it
222
- * can never release a different live reservation; a token that was already
223
- * rolled back or aged out of the window is a no-op (no double release);
224
- * rollback never advances the window (remaining reservations and their
225
- * timestamps are untouched).
226
- */
227
- rollback(reservation: BudgetReservation): void;
228
- }
229
- //# sourceMappingURL=quotaGovernor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"quotaGovernor.d.ts","sourceRoot":"","sources":["../../../../../../../../src/sheets/providers/google-sheets-api/transport/quotaGovernor.ts"],"names":[],"mappings":"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"}