@substrat-run/kernel 0.159.0 → 0.161.0
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/billing-retention.d.ts +46 -0
- package/dist/billing-retention.d.ts.map +1 -0
- package/dist/billing-retention.js +78 -0
- package/dist/billing-retention.js.map +1 -0
- package/dist/byte-stream.d.ts +142 -0
- package/dist/byte-stream.d.ts.map +1 -0
- package/dist/byte-stream.js +274 -0
- package/dist/byte-stream.js.map +1 -0
- package/dist/connection-landings.d.ts +15 -3
- package/dist/connection-landings.d.ts.map +1 -1
- package/dist/connection-landings.js +10 -2
- package/dist/connection-landings.js.map +1 -1
- package/dist/deadline-fetch.d.ts +34 -0
- package/dist/deadline-fetch.d.ts.map +1 -0
- package/dist/deadline-fetch.js +231 -0
- package/dist/deadline-fetch.js.map +1 -0
- package/dist/deployment-wire-auth.d.ts +125 -0
- package/dist/deployment-wire-auth.d.ts.map +1 -0
- package/dist/deployment-wire-auth.js +161 -0
- package/dist/deployment-wire-auth.js.map +1 -0
- package/dist/entity-trash.d.ts +65 -8
- package/dist/entity-trash.d.ts.map +1 -1
- package/dist/entity-trash.js +80 -12
- package/dist/entity-trash.js.map +1 -1
- package/dist/export-break.d.ts +6 -0
- package/dist/export-break.d.ts.map +1 -1
- package/dist/export-break.js +11 -0
- package/dist/export-break.js.map +1 -1
- package/dist/index.d.ts +19 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -8
- package/dist/index.js.map +1 -1
- package/dist/meter-days.d.ts +107 -0
- package/dist/meter-days.d.ts.map +1 -0
- package/dist/meter-days.js +230 -0
- package/dist/meter-days.js.map +1 -0
- package/dist/meters.d.ts +19 -1
- package/dist/meters.d.ts.map +1 -1
- package/dist/meters.js +0 -0
- package/dist/meters.js.map +1 -1
- package/dist/ops-failure-reference.d.ts +43 -0
- package/dist/ops-failure-reference.d.ts.map +1 -0
- package/dist/ops-failure-reference.js +42 -0
- package/dist/ops-failure-reference.js.map +1 -0
- package/dist/platform-request-cap.d.ts +9 -0
- package/dist/platform-request-cap.d.ts.map +1 -0
- package/dist/platform-request-cap.js +42 -0
- package/dist/platform-request-cap.js.map +1 -0
- package/dist/platform-sweep.d.ts +187 -7
- package/dist/platform-sweep.d.ts.map +1 -1
- package/dist/platform-sweep.js +388 -45
- package/dist/platform-sweep.js.map +1 -1
- package/dist/promote-review.d.ts +6 -0
- package/dist/promote-review.d.ts.map +1 -1
- package/dist/promote-review.js +9 -0
- package/dist/promote-review.js.map +1 -1
- package/dist/request-rollup.d.ts +161 -0
- package/dist/request-rollup.d.ts.map +1 -0
- package/dist/request-rollup.js +273 -0
- package/dist/request-rollup.js.map +1 -0
- package/dist/reserved-roles.d.ts +192 -4
- package/dist/reserved-roles.d.ts.map +1 -1
- package/dist/reserved-roles.js +314 -2
- package/dist/reserved-roles.js.map +1 -1
- package/dist/schedule-state.d.ts +5 -0
- package/dist/schedule-state.d.ts.map +1 -1
- package/dist/scope-host.d.ts +317 -15
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js +93 -2
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-lifecycle.d.ts +7 -0
- package/dist/scope-lifecycle.d.ts.map +1 -1
- package/dist/scope-lifecycle.js +7 -0
- package/dist/scope-lifecycle.js.map +1 -1
- package/dist/scope-record.d.ts +16 -5
- package/dist/scope-record.d.ts.map +1 -1
- package/dist/scope-record.js +72 -7
- package/dist/scope-record.js.map +1 -1
- package/dist/spine-restore.d.ts +7 -3
- package/dist/spine-restore.d.ts.map +1 -1
- package/dist/spine-restore.js +14 -3
- package/dist/spine-restore.js.map +1 -1
- package/dist/storage-gauge.d.ts +47 -13
- package/dist/storage-gauge.d.ts.map +1 -1
- package/dist/storage-gauge.js +84 -27
- package/dist/storage-gauge.js.map +1 -1
- package/dist/subject-redaction.d.ts +9 -3
- package/dist/subject-redaction.d.ts.map +1 -1
- package/dist/subject-redaction.js +23 -12
- package/dist/subject-redaction.js.map +1 -1
- package/dist/vertical-owners.d.ts +69 -0
- package/dist/vertical-owners.d.ts.map +1 -0
- package/dist/vertical-owners.js +108 -0
- package/dist/vertical-owners.js.map +1 -0
- package/package.json +2 -2
package/dist/scope-record.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { slug as slugSchema } from '@substrat-run/contracts';
|
|
1
|
+
import { scopeText, slug as slugSchema, substratError, verticalSlug } from '@substrat-run/contracts';
|
|
2
2
|
/**
|
|
3
3
|
* Resolve `ProvisionScopeInput`'s optional naming fields into the row both
|
|
4
4
|
* adapters write.
|
|
@@ -9,9 +9,11 @@ import { slug as slugSchema } from '@substrat-run/contracts';
|
|
|
9
9
|
* the contract tests — which run the same suite against both adapters — would
|
|
10
10
|
* still pass, because each adapter would be consistent with itself.
|
|
11
11
|
*
|
|
12
|
-
* The slug
|
|
13
|
-
* fails here, at provisioning, instead of at the first
|
|
14
|
-
* the scope already exists and the caller is someone else.
|
|
12
|
+
* The slug, kind, name and vertical are parsed rather than trusted (the boundary
|
|
13
|
+
* rule): an invalid one fails here, at provisioning, instead of at the first
|
|
14
|
+
* `listScopes` read, when the scope already exists and the caller is someone else.
|
|
15
|
+
* A default stands in only for an absent value: an empty or whitespace-only `kind`
|
|
16
|
+
* or `name` is refused, never defaulted.
|
|
15
17
|
*/
|
|
16
18
|
export function resolveScopeRecord(input) {
|
|
17
19
|
// A ULID lowercases into a valid slug ([0-9a-hjkmnp-tv-z]), so the default is
|
|
@@ -19,9 +21,9 @@ export function resolveScopeRecord(input) {
|
|
|
19
21
|
const slug = slugSchema.parse(input.slug ?? input.scopeId.toLowerCase());
|
|
20
22
|
return {
|
|
21
23
|
slug,
|
|
22
|
-
kind: input.kind ?? 'scope',
|
|
23
|
-
name: input.name ?? slug,
|
|
24
|
-
vertical: input.vertical ??
|
|
24
|
+
kind: textOf('kind', input.kind) ?? 'scope',
|
|
25
|
+
name: textOf('name', input.name) ?? slug,
|
|
26
|
+
vertical: verticalOf(input.vertical, input.verticalSource ?? 'input'),
|
|
25
27
|
storageShape: input.storageShape ?? 'A',
|
|
26
28
|
// No jurisdiction stated means `global` — unconstrained, the honest name for
|
|
27
29
|
// what an un-pinned scope already is (K-32). The old default was `null`, which
|
|
@@ -34,4 +36,67 @@ export function resolveScopeRecord(input) {
|
|
|
34
36
|
expiresAt: input.expiresAt ?? null,
|
|
35
37
|
};
|
|
36
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Map directory rows to `Scope`s the way `HostAdmin.listScopesReadable` answers: a row `map`
|
|
41
|
+
* throws on is named in `unreadable` by its stored ids and the fields that failed, and the rest
|
|
42
|
+
* are returned in order. One implementation for both adapters, so they name a bad row alike.
|
|
43
|
+
*/
|
|
44
|
+
export function readableScopes(rows, map) {
|
|
45
|
+
const out = { scopes: [], unreadable: [] };
|
|
46
|
+
for (const row of rows) {
|
|
47
|
+
try {
|
|
48
|
+
out.scopes.push(map(row));
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
out.unreadable.push({ scopeId: storedId(row.scope_id), tenantId: storedId(row.tenant_id), fields: failedFieldsOf(err) });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
/** A stored id as text, bounded: a corrupt row's id column is not trusted to be a ULID. */
|
|
57
|
+
const storedId = (value) => String(value).slice(0, 64);
|
|
58
|
+
/** The top-level field names a parse failure names, without the values it read. */
|
|
59
|
+
function failedFieldsOf(err) {
|
|
60
|
+
const issues = err?.issues;
|
|
61
|
+
if (!Array.isArray(issues))
|
|
62
|
+
return ['row'];
|
|
63
|
+
const fields = new Set();
|
|
64
|
+
for (const issue of issues) {
|
|
65
|
+
const head = Array.isArray(issue.path) ? issue.path[0] : undefined;
|
|
66
|
+
fields.add(typeof head === 'string' ? head : 'row');
|
|
67
|
+
}
|
|
68
|
+
return fields.size > 0 ? [...fields] : ['row'];
|
|
69
|
+
}
|
|
70
|
+
/** A `kind` or `name` as given, null when absent; an empty or whitespace-only one is refused. */
|
|
71
|
+
function textOf(field, value) {
|
|
72
|
+
if (value === undefined || value === null)
|
|
73
|
+
return null;
|
|
74
|
+
if (scopeText.safeParse(value).success)
|
|
75
|
+
return value;
|
|
76
|
+
return refuse(field, 'must not be empty or whitespace');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The vertical a scope runs, or null for none.
|
|
80
|
+
*
|
|
81
|
+
* One a caller names (`'input'`) is held to the registry's grammar (`verticalSlug`), so an empty
|
|
82
|
+
* or whitespace-only string is refused like any other value it does not admit. One copied from
|
|
83
|
+
* a scope that already exists (`'copy'`) is that scope's stored value, held only to what the
|
|
84
|
+
* directory's `scope` schema reads (non-empty), as it was before the grammar was held here: a
|
|
85
|
+
* stored `Todo` still lists, so its scope can still be snapshotted or given a sibling.
|
|
86
|
+
*/
|
|
87
|
+
function verticalOf(vertical, source) {
|
|
88
|
+
if (vertical === undefined || vertical === null)
|
|
89
|
+
return null;
|
|
90
|
+
if (source === 'copy')
|
|
91
|
+
return vertical.length > 0 ? vertical : refuse('vertical', 'must not be empty');
|
|
92
|
+
if (verticalSlug.safeParse(vertical).success)
|
|
93
|
+
return vertical;
|
|
94
|
+
return refuse('vertical', 'must be a vertical slug: lowercase letters, digits and hyphens, optionally prefixed by an owner slug and one /');
|
|
95
|
+
}
|
|
96
|
+
/** The standard refusal for one provisioning field, naming it. */
|
|
97
|
+
function refuse(field, message) {
|
|
98
|
+
throw substratError('validation_failed', `provisionScope: ${field} ${message}`, {
|
|
99
|
+
errors: [{ path: field, message }],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
37
102
|
//# sourceMappingURL=scope-record.js.map
|
package/dist/scope-record.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-record.js","sourceRoot":"","sources":["../src/scope-record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"scope-record.js","sourceRoot":"","sources":["../src/scope-record.ts"],"names":[],"mappings":"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"}
|
package/dist/spine-restore.d.ts
CHANGED
|
@@ -91,13 +91,17 @@ export declare const LEGACY_SCOPE_ROWS_BACKFILL: readonly string[];
|
|
|
91
91
|
*
|
|
92
92
|
* 0. map a pre-rename copy's `store_kind_*` tables and `kind` columns onto the driver names
|
|
93
93
|
* (`mapLegacyStoreDriverDump`);
|
|
94
|
-
* 1. refuse a table the directory does not build (`assertDirectoryTablesBuilt`),
|
|
95
|
-
*
|
|
94
|
+
* 1. refuse a table the directory does not build (`assertDirectoryTablesBuilt`), a dump with two
|
|
95
|
+
* open ownership periods of one slug (`assertOneOpenVerticalOwnerPeriod`, #2501), and a table
|
|
96
|
+
* that would pass `maxColumns` once the dump's unknown columns join this code's own;
|
|
96
97
|
* 2. add each column the dump carries and this code does not know, bare and lowercased, and
|
|
97
98
|
* refuse one named for the rowid (`spineColumnAdditions`);
|
|
98
99
|
* 3. insert every row by column name, against the columns read back after step 2
|
|
99
100
|
* (`spineRowsInsert`);
|
|
100
|
-
* 4. fill a pre-directory scope row's naming columns (`LEGACY_SCOPE_ROWS_BACKFILL`)
|
|
101
|
+
* 4. fill a pre-directory scope row's naming columns (`LEGACY_SCOPE_ROWS_BACKFILL`), close an
|
|
102
|
+
* open ownership period whose slug has no vertical, at `verticalOwnerNow()`
|
|
103
|
+
* (`verticalOwnersStrayCloseSql`), and open one for each vertical that has none
|
|
104
|
+
* (`VERTICAL_OWNERS_BACKFILL`, #2501);
|
|
101
105
|
* 5. backfill each kill switch's record (the schedule switch's, #1674, and the peer switch's,
|
|
102
106
|
* #2029) from the dump's own admin log, when the dump predates that record. One that carried
|
|
103
107
|
* it keeps its rows and is never backfilled over;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spine-restore.d.ts","sourceRoot":"","sources":["../src/spine-restore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spine-restore.d.ts","sourceRoot":"","sources":["../src/spine-restore.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIlD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI,CAGjG;AAED,iGAAiG;AACjG,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;AA2C9E;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAEtH;AASD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EACnD,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAC3C,MAAM,EAAE,CAmBV;AA4CD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAIvD,CAAC;AAsBF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,CAAA;CAAE,EAAE,EACtG,IAAI,EAAE;IACJ,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC;IACrE;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB,GACA,IAAI,CAmBN"}
|
package/dist/spine-restore.js
CHANGED
|
@@ -5,6 +5,7 @@ import { isSearchIndexTable } from './search-index.js';
|
|
|
5
5
|
import { SWITCH_KINDS, dumpCarriesSwitches, switchesBackfillSqlOf } from './system-switch-record.js';
|
|
6
6
|
import { dumpCarriesMembershipFences, membershipFencesBackfillSql } from './membership-fence.js';
|
|
7
7
|
import { mapLegacyStoreDriverDump } from './store-driver-releases.js';
|
|
8
|
+
import { VERTICAL_OWNERS_BACKFILL, assertOneOpenVerticalOwnerPeriod, verticalOwnerNow, verticalOwnersStrayCloseSql, } from './vertical-owners.js';
|
|
8
9
|
/**
|
|
9
10
|
* How a restore, fork or carry loads a dump's `_substrat_*` spine tables (#1883). One
|
|
10
11
|
* definition for both adapters' loaders, so the DO and the pure host build the same tables
|
|
@@ -200,13 +201,17 @@ function assertWithinColumnCap(tables, columnsOf, max) {
|
|
|
200
201
|
*
|
|
201
202
|
* 0. map a pre-rename copy's `store_kind_*` tables and `kind` columns onto the driver names
|
|
202
203
|
* (`mapLegacyStoreDriverDump`);
|
|
203
|
-
* 1. refuse a table the directory does not build (`assertDirectoryTablesBuilt`),
|
|
204
|
-
*
|
|
204
|
+
* 1. refuse a table the directory does not build (`assertDirectoryTablesBuilt`), a dump with two
|
|
205
|
+
* open ownership periods of one slug (`assertOneOpenVerticalOwnerPeriod`, #2501), and a table
|
|
206
|
+
* that would pass `maxColumns` once the dump's unknown columns join this code's own;
|
|
205
207
|
* 2. add each column the dump carries and this code does not know, bare and lowercased, and
|
|
206
208
|
* refuse one named for the rowid (`spineColumnAdditions`);
|
|
207
209
|
* 3. insert every row by column name, against the columns read back after step 2
|
|
208
210
|
* (`spineRowsInsert`);
|
|
209
|
-
* 4. fill a pre-directory scope row's naming columns (`LEGACY_SCOPE_ROWS_BACKFILL`)
|
|
211
|
+
* 4. fill a pre-directory scope row's naming columns (`LEGACY_SCOPE_ROWS_BACKFILL`), close an
|
|
212
|
+
* open ownership period whose slug has no vertical, at `verticalOwnerNow()`
|
|
213
|
+
* (`verticalOwnersStrayCloseSql`), and open one for each vertical that has none
|
|
214
|
+
* (`VERTICAL_OWNERS_BACKFILL`, #2501);
|
|
210
215
|
* 5. backfill each kill switch's record (the schedule switch's, #1674, and the peer switch's,
|
|
211
216
|
* #2029) from the dump's own admin log, when the dump predates that record. One that carried
|
|
212
217
|
* it keeps its rows and is never backfilled over;
|
|
@@ -219,6 +224,7 @@ export function loadDirectoryDump(tables, host) {
|
|
|
219
224
|
// A copy from before the store driver rename names its tables and key column the old way.
|
|
220
225
|
tables = mapLegacyStoreDriverDump(tables);
|
|
221
226
|
assertDirectoryTablesBuilt(tables.map((t) => t.name), host.columnsOf);
|
|
227
|
+
assertOneOpenVerticalOwnerPeriod(tables);
|
|
222
228
|
if (host.maxColumns !== undefined)
|
|
223
229
|
assertWithinColumnCap(tables, host.columnsOf, host.maxColumns);
|
|
224
230
|
for (const t of tables)
|
|
@@ -230,6 +236,11 @@ export function loadDirectoryDump(tables, host) {
|
|
|
230
236
|
}
|
|
231
237
|
for (const stmt of LEGACY_SCOPE_ROWS_BACKFILL)
|
|
232
238
|
host.exec(stmt);
|
|
239
|
+
// #2501: a period left open for a slug the dump has no row for is closed, on the clock every
|
|
240
|
+
// period stamp is read on (not `host.now()`); then a dump from before the history comes back
|
|
241
|
+
// with one period per vertical.
|
|
242
|
+
host.exec(verticalOwnersStrayCloseSql(verticalOwnerNow()));
|
|
243
|
+
host.exec(VERTICAL_OWNERS_BACKFILL);
|
|
233
244
|
const names = tables.map((t) => t.name);
|
|
234
245
|
for (const kind of SWITCH_KINDS)
|
|
235
246
|
if (!dumpCarriesSwitches(names, kind))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spine-restore.js","sourceRoot":"","sources":["../src/spine-restore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACrG,OAAO,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"spine-restore.js","sourceRoot":"","sources":["../src/spine-restore.ts"],"names":[],"mappings":"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"}
|
package/dist/storage-gauge.d.ts
CHANGED
|
@@ -20,8 +20,20 @@ import type { RedactionSql } from './subject-redaction.js';
|
|
|
20
20
|
* pass, ahead of every scope that can be read, and its error would reach every pass's
|
|
21
21
|
* failure digest. With it, a failing scope is tried once a day like any other, while its last
|
|
22
22
|
* good sample stands.
|
|
23
|
+
*
|
|
24
|
+
* `_substrat_scope_attachment_storage` (#2501) is the database table's shape for attachment
|
|
25
|
+
* bytes: the day's latest reading of what the scope's attachment rows sum to, read in the same
|
|
26
|
+
* attempt as the database. It sits beside the database figure and never inside it.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SCOPE_STORAGE_DDL = "\n CREATE TABLE IF NOT EXISTS _substrat_scope_storage (\n scope_id TEXT NOT NULL,\n day TEXT NOT NULL,\n tenant_id TEXT NOT NULL,\n bytes INTEGER NOT NULL,\n read_at TEXT NOT NULL,\n PRIMARY KEY (scope_id, day)\n );\n CREATE INDEX IF NOT EXISTS _substrat_scope_storage_tenant ON _substrat_scope_storage (tenant_id, day);\n CREATE INDEX IF NOT EXISTS _substrat_scope_storage_day ON _substrat_scope_storage (day);\n CREATE TABLE IF NOT EXISTS _substrat_scope_storage_attempts (\n scope_id TEXT PRIMARY KEY,\n tenant_id TEXT NOT NULL,\n attempted_at TEXT NOT NULL,\n error TEXT\n );\n CREATE TABLE IF NOT EXISTS _substrat_scope_store_storage (\n scope_id TEXT NOT NULL,\n binding TEXT NOT NULL,\n day TEXT NOT NULL,\n tenant_id TEXT NOT NULL,\n bytes INTEGER NOT NULL,\n read_at TEXT NOT NULL,\n PRIMARY KEY (scope_id, binding, day)\n );\n CREATE INDEX IF NOT EXISTS _substrat_scope_store_storage_tenant ON _substrat_scope_store_storage (tenant_id, day);\n CREATE TABLE IF NOT EXISTS _substrat_scope_attachment_storage (\n scope_id TEXT NOT NULL,\n day TEXT NOT NULL,\n tenant_id TEXT NOT NULL,\n bytes INTEGER NOT NULL,\n read_at TEXT NOT NULL,\n PRIMARY KEY (scope_id, day)\n );\n CREATE INDEX IF NOT EXISTS _substrat_scope_attachment_storage_tenant ON _substrat_scope_attachment_storage (tenant_id, day);\n CREATE INDEX IF NOT EXISTS _substrat_scope_attachment_storage_day ON _substrat_scope_attachment_storage (day);\n";
|
|
29
|
+
/**
|
|
30
|
+
* A scope's attachment bytes (#2501), as its own database records them: the sum of the sizes on
|
|
31
|
+
* its `_substrat_attachments` rows, not what the blob store holds. Bytes in the blob store that no
|
|
32
|
+
* row names (an orphan the sweep has not collected, #2314) are not in it, and a fork or snapshot
|
|
33
|
+
* that is itself a stored scope counts its copied rows again, though they name the parent's blobs.
|
|
34
|
+
* Both adapters read it with this one statement.
|
|
23
35
|
*/
|
|
24
|
-
export declare const
|
|
36
|
+
export declare const ATTACHMENT_BYTES_SQL = "SELECT COALESCE(SUM(size), 0) AS bytes FROM _substrat_attachments";
|
|
25
37
|
/**
|
|
26
38
|
* The statuses a scope that holds a store can be in: every status but `provisioning` (no
|
|
27
39
|
* store yet) and `reaped` (its store is gone). A non-serving scope (suspended, archiving,
|
|
@@ -65,6 +77,12 @@ export interface ScopeStorageReadingInput {
|
|
|
65
77
|
binding: string;
|
|
66
78
|
bytes: number;
|
|
67
79
|
}[];
|
|
80
|
+
/**
|
|
81
|
+
* Attachment bytes read in the same attempt (#2501): what the scope's attachment rows sum to.
|
|
82
|
+
* Present means this attempt measured them, and writes the day's attachment sample. Absent
|
|
83
|
+
* leaves it as it is: the read was not made, failed, or the deployment cannot make it.
|
|
84
|
+
*/
|
|
85
|
+
attachments?: number;
|
|
68
86
|
}
|
|
69
87
|
/** When the phase last tried a scope (#1524), and why it failed if it did. */
|
|
70
88
|
export interface ScopeStorageAttempt {
|
|
@@ -77,7 +95,9 @@ export interface ScopeStorageAttempt {
|
|
|
77
95
|
* Filter for `listScopeStorage`. `latest` returns one row per stored scope, its most
|
|
78
96
|
* recent day, and ignores `since`/`until`/`limit`: that set is bounded by the scope count,
|
|
79
97
|
* the same as `listScopes`. Otherwise it is history, ordered (scope, day), `since`/`until`
|
|
80
|
-
* inclusive UTC days, at most `limit` rows.
|
|
98
|
+
* inclusive UTC days, at most `limit` rows. History also holds a reaped scope's days (#2515),
|
|
99
|
+
* which count against `limit` as any row does; there is no cursor, so a tenant with many
|
|
100
|
+
* reaped scopes reaches the cap sooner and the scopes sorting last can be cut off.
|
|
81
101
|
*/
|
|
82
102
|
export interface ScopeStorageFilter {
|
|
83
103
|
tenantId?: TenantId;
|
|
@@ -89,21 +109,19 @@ export interface ScopeStorageFilter {
|
|
|
89
109
|
}
|
|
90
110
|
/** The UTC day a reading belongs to. */
|
|
91
111
|
export declare function storageGaugeDay(readAt: string): string;
|
|
92
|
-
/**
|
|
93
|
-
* The first day retention keeps: thirteen calendar months before `nowMs`, as a UTC day. The
|
|
94
|
-
* day is clamped to the target month's last day, so the 31st of a month counts back to the
|
|
95
|
-
* 28th, 29th or 30th rather than rolling forward into the month after.
|
|
96
|
-
*/
|
|
112
|
+
/** The first day retention keeps: thirteen calendar months before `nowMs`, as a UTC day. */
|
|
97
113
|
export declare function storageRetentionHorizon(nowMs: number): string;
|
|
98
114
|
/**
|
|
99
115
|
* Record attempts, a statement or two each. Every row is written only for a scope the
|
|
100
116
|
* directory holds UNDER THAT TENANT and has not reaped, so a reading can never land in another
|
|
101
117
|
* tenant's figure, and a scope reaped while its read was in flight leaves no row behind.
|
|
102
118
|
*
|
|
103
|
-
* Every attempt replaces the scope's attempt row.
|
|
104
|
-
* sample, which replaces an older reading of that day and never a newer one; a failed
|
|
105
|
-
* leaves
|
|
106
|
-
*
|
|
119
|
+
* Every attempt replaces the scope's attempt row. One with a database size also upserts the
|
|
120
|
+
* day's sample, which replaces an older reading of that day and never a newer one; a failed
|
|
121
|
+
* database read (no size) leaves every sample alone, so the last good reading stands. The store
|
|
122
|
+
* and attachment samples beside it are written only when the attempt carries them, so a failed
|
|
123
|
+
* read of either leaves its own sample alone while the database sample is still written.
|
|
124
|
+
* Returns how many DATABASE sample rows were written.
|
|
107
125
|
*/
|
|
108
126
|
export declare function recordScopeStorageRows(sql: RedactionSql, readings: readonly ScopeStorageReadingInput[]): number;
|
|
109
127
|
/** Read samples — see `ScopeStorageFilter`. Every row is parsed on the way out. */
|
|
@@ -113,7 +131,10 @@ export declare function listScopeStorageRows(sql: RedactionSql, filter?: ScopeSt
|
|
|
113
131
|
* what a meter reading names failing scopes from. `tenantId` narrows to one tenant.
|
|
114
132
|
*/
|
|
115
133
|
export declare function listScopeStorageAttemptRows(sql: RedactionSql, tenantId?: TenantId): ScopeStorageAttempt[];
|
|
116
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* Delete at most `limit` samples older than retention, oldest first: the databases' first, then
|
|
136
|
+
* the stores' and the attachments' with what the limit leaves. Returns how many went.
|
|
137
|
+
*/
|
|
117
138
|
export declare function pruneScopeStorageRows(sql: RedactionSql, nowMs: number, limit: number): number;
|
|
118
139
|
/**
|
|
119
140
|
* Bindings on the latest day that measured stores for the scope. A binding absent that day has
|
|
@@ -124,7 +145,18 @@ export declare function listScopeStoreStorageRows(sql: RedactionSql, tenantId?:
|
|
|
124
145
|
bytes: number;
|
|
125
146
|
readAt: string;
|
|
126
147
|
}[];
|
|
127
|
-
/**
|
|
148
|
+
/** Each stored scope's latest attachment sample (#2501), as the gauge folds it. */
|
|
149
|
+
export declare function listScopeAttachmentStorageRows(sql: RedactionSql, tenantId?: TenantId): {
|
|
150
|
+
tenantId: TenantId;
|
|
151
|
+
bytes: number;
|
|
152
|
+
}[];
|
|
153
|
+
/**
|
|
154
|
+
* A reap ends a scope's measuring (#2515): the attempt row goes, the day rows stay. They are the
|
|
155
|
+
* bytes the scope held on the days it held them, which a later invoice for that month is cut
|
|
156
|
+
* from, so they leave only with retention (`pruneScopeStorageRows`) or the tenant's own reap.
|
|
157
|
+
*/
|
|
158
|
+
export declare function retireScopeStorage(sql: RedactionSql, scopeId: string): void;
|
|
159
|
+
/** Drop everything of a scope's: a deleted fork's rows have no scope row left to be read through. */
|
|
128
160
|
export declare function forgetScopeStorage(sql: RedactionSql, scopeId: string): void;
|
|
129
161
|
/**
|
|
130
162
|
* Fold latest samples into one gauge. `total` is the caller's count of stored scopes
|
|
@@ -140,5 +172,7 @@ export declare function foldStorageGauge(samples: readonly {
|
|
|
140
172
|
error: string | null;
|
|
141
173
|
}[], stores?: readonly {
|
|
142
174
|
bytes: number;
|
|
175
|
+
}[], attachments?: readonly {
|
|
176
|
+
bytes: number;
|
|
143
177
|
}[]): StorageGauge;
|
|
144
178
|
//# sourceMappingURL=storage-gauge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-gauge.d.ts","sourceRoot":"","sources":["../src/storage-gauge.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"storage-gauge.d.ts","sourceRoot":"","sources":["../src/storage-gauge.ts"],"names":[],"mappings":"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"}
|
package/dist/storage-gauge.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { STORAGE_EXCLUSIONS, scopeStorageSample, } from '@substrat-run/contracts';
|
|
2
2
|
import { assertRowLimit, boundedRetentionDelete } from './scope-host.js';
|
|
3
|
+
import { utcDayMonthsBefore } from './billing-retention.js';
|
|
3
4
|
/**
|
|
4
5
|
* The stored storage gauge (#1524), as statements both adapters run against their directory:
|
|
5
6
|
* the SQLite host over better-sqlite3, the hosted one inside ControlPlaneDO. Written once so
|
|
@@ -20,6 +21,10 @@ import { assertRowLimit, boundedRetentionDelete } from './scope-host.js';
|
|
|
20
21
|
* pass, ahead of every scope that can be read, and its error would reach every pass's
|
|
21
22
|
* failure digest. With it, a failing scope is tried once a day like any other, while its last
|
|
22
23
|
* good sample stands.
|
|
24
|
+
*
|
|
25
|
+
* `_substrat_scope_attachment_storage` (#2501) is the database table's shape for attachment
|
|
26
|
+
* bytes: the day's latest reading of what the scope's attachment rows sum to, read in the same
|
|
27
|
+
* attempt as the database. It sits beside the database figure and never inside it.
|
|
23
28
|
*/
|
|
24
29
|
export const SCOPE_STORAGE_DDL = `
|
|
25
30
|
CREATE TABLE IF NOT EXISTS _substrat_scope_storage (
|
|
@@ -48,7 +53,25 @@ export const SCOPE_STORAGE_DDL = `
|
|
|
48
53
|
PRIMARY KEY (scope_id, binding, day)
|
|
49
54
|
);
|
|
50
55
|
CREATE INDEX IF NOT EXISTS _substrat_scope_store_storage_tenant ON _substrat_scope_store_storage (tenant_id, day);
|
|
56
|
+
CREATE TABLE IF NOT EXISTS _substrat_scope_attachment_storage (
|
|
57
|
+
scope_id TEXT NOT NULL,
|
|
58
|
+
day TEXT NOT NULL,
|
|
59
|
+
tenant_id TEXT NOT NULL,
|
|
60
|
+
bytes INTEGER NOT NULL,
|
|
61
|
+
read_at TEXT NOT NULL,
|
|
62
|
+
PRIMARY KEY (scope_id, day)
|
|
63
|
+
);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS _substrat_scope_attachment_storage_tenant ON _substrat_scope_attachment_storage (tenant_id, day);
|
|
65
|
+
CREATE INDEX IF NOT EXISTS _substrat_scope_attachment_storage_day ON _substrat_scope_attachment_storage (day);
|
|
51
66
|
`;
|
|
67
|
+
/**
|
|
68
|
+
* A scope's attachment bytes (#2501), as its own database records them: the sum of the sizes on
|
|
69
|
+
* its `_substrat_attachments` rows, not what the blob store holds. Bytes in the blob store that no
|
|
70
|
+
* row names (an orphan the sweep has not collected, #2314) are not in it, and a fork or snapshot
|
|
71
|
+
* that is itself a stored scope counts its copied rows again, though they name the parent's blobs.
|
|
72
|
+
* Both adapters read it with this one statement.
|
|
73
|
+
*/
|
|
74
|
+
export const ATTACHMENT_BYTES_SQL = 'SELECT COALESCE(SUM(size), 0) AS bytes FROM _substrat_attachments';
|
|
52
75
|
/**
|
|
53
76
|
* The statuses a scope that holds a store can be in: every status but `provisioning` (no
|
|
54
77
|
* store yet) and `reaped` (its store is gone). A non-serving scope (suspended, archiving,
|
|
@@ -83,27 +106,21 @@ export const STORAGE_HISTORY_LIMIT_DEFAULT = 1_000;
|
|
|
83
106
|
export function storageGaugeDay(readAt) {
|
|
84
107
|
return new Date(readAt).toISOString().slice(0, 10);
|
|
85
108
|
}
|
|
86
|
-
/**
|
|
87
|
-
* The first day retention keeps: thirteen calendar months before `nowMs`, as a UTC day. The
|
|
88
|
-
* day is clamped to the target month's last day, so the 31st of a month counts back to the
|
|
89
|
-
* 28th, 29th or 30th rather than rolling forward into the month after.
|
|
90
|
-
*/
|
|
109
|
+
/** The first day retention keeps: thirteen calendar months before `nowMs`, as a UTC day. */
|
|
91
110
|
export function storageRetentionHorizon(nowMs) {
|
|
92
|
-
|
|
93
|
-
const month = now.getUTCMonth() - STORAGE_GAUGE_RETENTION_MONTHS;
|
|
94
|
-
// Day 0 of the following month is the last day of the target month.
|
|
95
|
-
const lastDay = new Date(Date.UTC(now.getUTCFullYear(), month + 1, 0)).getUTCDate();
|
|
96
|
-
return new Date(Date.UTC(now.getUTCFullYear(), month, Math.min(now.getUTCDate(), lastDay))).toISOString().slice(0, 10);
|
|
111
|
+
return utcDayMonthsBefore(nowMs, STORAGE_GAUGE_RETENTION_MONTHS);
|
|
97
112
|
}
|
|
98
113
|
/**
|
|
99
114
|
* Record attempts, a statement or two each. Every row is written only for a scope the
|
|
100
115
|
* directory holds UNDER THAT TENANT and has not reaped, so a reading can never land in another
|
|
101
116
|
* tenant's figure, and a scope reaped while its read was in flight leaves no row behind.
|
|
102
117
|
*
|
|
103
|
-
* Every attempt replaces the scope's attempt row.
|
|
104
|
-
* sample, which replaces an older reading of that day and never a newer one; a failed
|
|
105
|
-
* leaves
|
|
106
|
-
*
|
|
118
|
+
* Every attempt replaces the scope's attempt row. One with a database size also upserts the
|
|
119
|
+
* day's sample, which replaces an older reading of that day and never a newer one; a failed
|
|
120
|
+
* database read (no size) leaves every sample alone, so the last good reading stands. The store
|
|
121
|
+
* and attachment samples beside it are written only when the attempt carries them, so a failed
|
|
122
|
+
* read of either leaves its own sample alone while the database sample is still written.
|
|
123
|
+
* Returns how many DATABASE sample rows were written.
|
|
107
124
|
*/
|
|
108
125
|
export function recordScopeStorageRows(sql, readings) {
|
|
109
126
|
let recorded = 0;
|
|
@@ -125,6 +142,16 @@ export function recordScopeStorageRows(sql, readings) {
|
|
|
125
142
|
RETURNING 1`, [storageGaugeDay(readAt), r.bytes, readAt, r.scopeId, r.tenantId]).length;
|
|
126
143
|
if (r.stores)
|
|
127
144
|
recordScopeStoreRows(sql, r, readAt);
|
|
145
|
+
if (r.attachments !== undefined && Number.isInteger(r.attachments) && r.attachments >= 0) {
|
|
146
|
+
// The database sample's rule: the day's latest reading, never replaced by an older one. Its
|
|
147
|
+
// own literal statement, not one shared with the table above: lint:attachment-writers reads
|
|
148
|
+
// every INSERT's target, and a computed one is a writer it cannot see.
|
|
149
|
+
sql(`INSERT INTO _substrat_scope_attachment_storage (scope_id, day, tenant_id, bytes, read_at)
|
|
150
|
+
SELECT scope_id, ?, tenant_id, ?, ? FROM scopes
|
|
151
|
+
WHERE scope_id = ? AND tenant_id = ? AND ${holdsStoreSql()}
|
|
152
|
+
ON CONFLICT (scope_id, day) DO UPDATE SET bytes = excluded.bytes, read_at = excluded.read_at
|
|
153
|
+
WHERE excluded.read_at >= _substrat_scope_attachment_storage.read_at`, [storageGaugeDay(readAt), r.attachments, readAt, r.scopeId, r.tenantId]);
|
|
154
|
+
}
|
|
128
155
|
}
|
|
129
156
|
return recorded;
|
|
130
157
|
}
|
|
@@ -162,7 +189,9 @@ function recordScopeStoreRows(sql, reading, readAt) {
|
|
|
162
189
|
}
|
|
163
190
|
/** Read samples — see `ScopeStorageFilter`. Every row is parsed on the way out. */
|
|
164
191
|
export function listScopeStorageRows(sql, filter = {}) {
|
|
165
|
-
|
|
192
|
+
// History also reads a reaped scope's days (#2515): its storage is gone, but the bytes it held
|
|
193
|
+
// on those days are what a later invoice is cut from. `latest` stays on scopes that hold a store.
|
|
194
|
+
const where = [filter.latest ? holdsStoreSql('s.') : `(${holdsStoreSql('s.')} OR s.status = 'reaped')`];
|
|
166
195
|
const params = [];
|
|
167
196
|
if (filter.tenantId) {
|
|
168
197
|
where.push('s.tenant_id = ?');
|
|
@@ -193,8 +222,8 @@ export function listScopeStorageRows(sql, filter = {}) {
|
|
|
193
222
|
tail = ' LIMIT ?';
|
|
194
223
|
params.push(Math.min(limit, STORAGE_HISTORY_LIMIT_MAX));
|
|
195
224
|
}
|
|
196
|
-
// The join to `scopes`
|
|
197
|
-
//
|
|
225
|
+
// The join to `scopes` keeps a fork's leftovers (its row is gone) and a scope that never held
|
|
226
|
+
// a store out of every read; a reaped scope's tombstone row is what admits its kept days.
|
|
198
227
|
const rows = sql(`SELECT g.tenant_id, g.scope_id, g.day, g.bytes, g.read_at
|
|
199
228
|
FROM scopes s
|
|
200
229
|
JOIN _substrat_scope_storage g ON g.scope_id = s.scope_id AND g.tenant_id = s.tenant_id${latestDay}
|
|
@@ -225,16 +254,19 @@ export function listScopeStorageAttemptRows(sql, tenantId) {
|
|
|
225
254
|
error: r.error,
|
|
226
255
|
}));
|
|
227
256
|
}
|
|
228
|
-
/**
|
|
257
|
+
/**
|
|
258
|
+
* Delete at most `limit` samples older than retention, oldest first: the databases' first, then
|
|
259
|
+
* the stores' and the attachments' with what the limit leaves. Returns how many went.
|
|
260
|
+
*/
|
|
229
261
|
export function pruneScopeStorageRows(sql, nowMs, limit) {
|
|
230
262
|
const horizon = storageRetentionHorizon(nowMs);
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return
|
|
263
|
+
let remaining = assertRowLimit('limit', limit);
|
|
264
|
+
for (const table of ['_substrat_scope_storage', '_substrat_scope_store_storage', '_substrat_scope_attachment_storage']) {
|
|
265
|
+
if (remaining === 0)
|
|
266
|
+
break;
|
|
267
|
+
remaining -= sql(boundedRetentionDelete(table, 'day'), [horizon, remaining]).length;
|
|
268
|
+
}
|
|
269
|
+
return limit - remaining;
|
|
238
270
|
}
|
|
239
271
|
/**
|
|
240
272
|
* Bindings on the latest day that measured stores for the scope. A binding absent that day has
|
|
@@ -252,11 +284,33 @@ export function listScopeStoreStorageRows(sql, tenantId) {
|
|
|
252
284
|
ORDER BY g.scope_id, g.binding`, tenantId ? [tenantId] : []);
|
|
253
285
|
return rows.map((r) => ({ tenantId: r.tenant_id, bytes: r.bytes, readAt: r.read_at }));
|
|
254
286
|
}
|
|
255
|
-
/**
|
|
287
|
+
/** Each stored scope's latest attachment sample (#2501), as the gauge folds it. */
|
|
288
|
+
export function listScopeAttachmentStorageRows(sql, tenantId) {
|
|
289
|
+
const rows = sql(`SELECT g.tenant_id, g.bytes
|
|
290
|
+
FROM scopes s
|
|
291
|
+
JOIN _substrat_scope_attachment_storage g ON g.scope_id = s.scope_id AND g.tenant_id = s.tenant_id
|
|
292
|
+
AND g.day = (
|
|
293
|
+
SELECT MAX(m.day) FROM _substrat_scope_attachment_storage m
|
|
294
|
+
WHERE m.scope_id = s.scope_id AND m.tenant_id = s.tenant_id
|
|
295
|
+
)
|
|
296
|
+
WHERE ${holdsStoreSql('s.')}${tenantId ? ' AND s.tenant_id = ?' : ''}
|
|
297
|
+
ORDER BY g.scope_id`, tenantId ? [tenantId] : []);
|
|
298
|
+
return rows.map((r) => ({ tenantId: r.tenant_id, bytes: r.bytes }));
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* A reap ends a scope's measuring (#2515): the attempt row goes, the day rows stay. They are the
|
|
302
|
+
* bytes the scope held on the days it held them, which a later invoice for that month is cut
|
|
303
|
+
* from, so they leave only with retention (`pruneScopeStorageRows`) or the tenant's own reap.
|
|
304
|
+
*/
|
|
305
|
+
export function retireScopeStorage(sql, scopeId) {
|
|
306
|
+
sql('DELETE FROM _substrat_scope_storage_attempts WHERE scope_id = ?', [scopeId]);
|
|
307
|
+
}
|
|
308
|
+
/** Drop everything of a scope's: a deleted fork's rows have no scope row left to be read through. */
|
|
256
309
|
export function forgetScopeStorage(sql, scopeId) {
|
|
257
310
|
sql('DELETE FROM _substrat_scope_storage WHERE scope_id = ?', [scopeId]);
|
|
258
311
|
sql('DELETE FROM _substrat_scope_storage_attempts WHERE scope_id = ?', [scopeId]);
|
|
259
312
|
sql('DELETE FROM _substrat_scope_store_storage WHERE scope_id = ?', [scopeId]);
|
|
313
|
+
sql('DELETE FROM _substrat_scope_attachment_storage WHERE scope_id = ?', [scopeId]);
|
|
260
314
|
}
|
|
261
315
|
/**
|
|
262
316
|
* Fold latest samples into one gauge. `total` is the caller's count of stored scopes
|
|
@@ -264,7 +318,7 @@ export function forgetScopeStorage(sql, scopeId) {
|
|
|
264
318
|
* (`listScopeStorage({ latest })`), and attempts the latest per stored scope
|
|
265
319
|
* (`listScopeStorageAttempts`).
|
|
266
320
|
*/
|
|
267
|
-
export function foldStorageGauge(samples, total, attempts = [], stores) {
|
|
321
|
+
export function foldStorageGauge(samples, total, attempts = [], stores, attachments) {
|
|
268
322
|
let failing = 0;
|
|
269
323
|
let lastFailed = null;
|
|
270
324
|
for (const a of attempts) {
|
|
@@ -296,6 +350,9 @@ export function foldStorageGauge(samples, total, attempts = [], stores) {
|
|
|
296
350
|
failing,
|
|
297
351
|
lastFailedAt: lastFailed,
|
|
298
352
|
...(stores && stores.length > 0 ? { stores: { bytes: storeBytes ?? 0, sampled: stores.length } } : {}),
|
|
353
|
+
...(attachments && attachments.length > 0
|
|
354
|
+
? { attachments: { bytes: attachments.reduce((sum, row) => sum + row.bytes, 0), sampled: attachments.length } }
|
|
355
|
+
: {}),
|
|
299
356
|
};
|
|
300
357
|
}
|
|
301
358
|
//# sourceMappingURL=storage-gauge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-gauge.js","sourceRoot":"","sources":["../src/storage-gauge.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GAKnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"storage-gauge.js","sourceRoot":"","sources":["../src/storage-gauge.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GAKnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqChC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mEAAmE,CAAC;AAExG;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,CAAU,CAAC;AAE/F;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAA6D;IACtF,IAAI,CAAE,qBAA2C,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACvF,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,IAAI,KAAK,CAAC,kBAAkB,KAAK,cAAc,CAAC,CAAC;AACzH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,KAAK,GAAG,EAAE;IACtC,OAAO,CACL,GAAG,KAAK,qEAAqE;QAC7E,IAAI,KAAK,2CAA2C,KAAK,yCAAyC,CACnG,CAAC;AACJ,CAAC;AAED,0GAA0G;AAC1G,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAEjD,yEAAyE;AACzE,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAE7C,kFAAkF;AAClF,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAChD,MAAM,CAAC,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAiDnD,wCAAwC;AACxC,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,OAAO,kBAAkB,CAAC,KAAK,EAAE,8BAA8B,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAiB,EAAE,QAA6C;IACrG,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACzE,GAAG,CACD;;mDAE6C,aAAa,EAAE;;qFAEmB,EAC/E,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CACjD,CAAC;QACF,IAAI,CAAC,EAAE;YAAE,SAAS;QAClB,QAAQ,IAAI,GAAG,CACb;;mDAE6C,aAAa,EAAE;;;mBAG/C,EACb,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAClE,CAAC,MAAM,CAAC;QACT,IAAI,CAAC,CAAC,MAAM;YAAE,oBAAoB,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,CAAC,WAAW,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,EAAE,CAAC;YACzF,4FAA4F;YAC5F,4FAA4F;YAC5F,uEAAuE;YACvE,GAAG,CACD;;qDAE6C,aAAa,EAAE;;+EAEW,EACvE,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CACxE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,GAAiB,EAAE,OAAiC,EAAE,MAAc;IAChG,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,GAAG,CACf;+EAC2E,EAC3E,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,CACjD,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO;IAC7B,GAAG,CACD;;;;sDAIkD,aAAa,EAAE;UAC3D,EACN,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAC5E,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CACxC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CACzF,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnE,GAAG,CACD;;mDAE6C,aAAa,EAAE;;wEAEM,EAClE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAC7E,CAAC;IACJ,CAAC;AACH,CAAC;AAUD,mFAAmF;AACnF,MAAM,UAAU,oBAAoB,CAAC,GAAiB,EAAE,MAAM,GAAuB,EAAE;IACrF,+FAA+F;IAC/F,kGAAkG;IAClG,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAClH,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,2FAA2F;IAC3F,wFAAwF;IACxF,kFAAkF;IAClF,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,SAAS,GAAG,+FAA+F,CAAC;IAC9G,CAAC;SAAM,CAAC;QACN,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,6BAA6B,CAAC,CAAC;QACrF,IAAI,GAAG,UAAU,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,8FAA8F;IAC9F,0FAA0F;IAC1F,MAAM,IAAI,GAAG,GAAG,CACd;;gGAE4F,SAAS;cAC3F,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;kCACC,IAAI,EAAE,EACpC,MAAM,CACQ,CAAC;IACjB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACpB,kBAAkB,CAAC,KAAK,CAAC;QACvB,QAAQ,EAAE,CAAC,CAAC,SAAS;QACrB,OAAO,EAAE,CAAC,CAAC,QAAQ;QACnB,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,MAAM,EAAE,CAAC,CAAC,OAAO;KAClB,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,GAAiB,EAAE,QAAmB;IAChF,MAAM,IAAI,GAAG,GAAG,CACd;;;cAGU,aAAa,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;0BAChD,EACtB,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAC8D,CAAC;IAC3F,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtB,QAAQ,EAAE,CAAC,CAAC,SAAqB;QACjC,OAAO,EAAE,CAAC,CAAC,QAAmB;QAC9B,WAAW,EAAE,CAAC,CAAC,YAAY;QAC3B,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAiB,EAAE,KAAa,EAAE,KAAa;IACnF,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,CAAC,yBAAyB,EAAE,+BAA+B,EAAE,oCAAoC,CAAC,EAAE,CAAC;QACvH,IAAI,SAAS,KAAK,CAAC;YAAE,MAAM;QAC3B,SAAS,IAAI,GAAG,CAAC,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IACtF,CAAC;IACD,OAAO,KAAK,GAAG,SAAS,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,GAAiB,EACjB,QAAmB;IAEnB,MAAM,IAAI,GAAG,GAAG,CACd;;;;;;;kCAO8B,aAAa,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;qCACzD,EACjC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CACgC,CAAC;IAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,SAAqB,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AACrG,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,8BAA8B,CAAC,GAAiB,EAAE,QAAmB;IACnF,MAAM,IAAI,GAAG,GAAG,CACd;;;;;;;cAOU,aAAa,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;0BAChD,EACtB,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CACe,CAAC;IAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,SAAqB,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAiB,EAAE,OAAe;IACnE,GAAG,CAAC,iEAAiE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,kBAAkB,CAAC,GAAiB,EAAE,OAAe;IACnE,GAAG,CAAC,wDAAwD,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACzE,GAAG,CAAC,iEAAiE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAClF,GAAG,CAAC,8DAA8D,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/E,GAAG,CAAC,mEAAmE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAqD,EACrD,KAAa,EACb,QAAQ,GAA6D,EAAE,EACvE,MAAqC,EACrC,WAA0C;IAE1C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI;YAAE,SAAS;QAC/B,OAAO,IAAI,CAAC,CAAC;QACb,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,GAAG,UAAU;YAAE,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC;IACpF,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;QACjB,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;YAAE,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;QAC5D,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;YAAE,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9D,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACpE,OAAO;QACL,KAAK,EAAE,iBAAiB;QACxB,QAAQ,EAAE,CAAC,GAAG,kBAAkB,CAAC;QACjC,KAAK;QACL,OAAO,EAAE,OAAO,CAAC,MAAM;QACvB,KAAK;QACL,YAAY,EAAE,MAAsC;QACpD,YAAY,EAAE,MAAsC;QACpD,OAAO;QACP,YAAY,EAAE,UAA0C;QACxD,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtG,GAAG,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;YACvC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,EAAE;YAC/G,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC"}
|