@madewithremy/admin 0.1.14 → 0.1.16
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/index.d.ts +156 -44
- package/dist/index.js +76 -12
- package/dist/index.js.map +1 -1
- package/dist/prod.js +170 -95
- package/package.json +1 -1
package/dist/prod.js
CHANGED
|
@@ -342,6 +342,62 @@ function statsForMethod(ctx, methodId, params = {}) {
|
|
|
342
342
|
);
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
+
// src/sleep.ts
|
|
346
|
+
function sleep(ms) {
|
|
347
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/poll.ts
|
|
351
|
+
async function pollUntil(read, isSettled, options) {
|
|
352
|
+
const start2 = Date.now();
|
|
353
|
+
let movedAt = start2;
|
|
354
|
+
let lastKey;
|
|
355
|
+
let transientSince = null;
|
|
356
|
+
while (true) {
|
|
357
|
+
let value;
|
|
358
|
+
try {
|
|
359
|
+
value = await read();
|
|
360
|
+
transientSince = null;
|
|
361
|
+
} catch (err) {
|
|
362
|
+
if (!isTransientError(err)) {
|
|
363
|
+
throw err;
|
|
364
|
+
}
|
|
365
|
+
transientSince ??= Date.now();
|
|
366
|
+
if (Date.now() - transientSince > TRANSIENT_GRACE_MS) {
|
|
367
|
+
throw err;
|
|
368
|
+
}
|
|
369
|
+
options.onProgress?.(
|
|
370
|
+
`retrying after a gateway error\u2026 (${elapsedSeconds(start2)}s)`
|
|
371
|
+
);
|
|
372
|
+
await sleep(options.pollMs);
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (isSettled(value)) {
|
|
376
|
+
return { settled: true, value };
|
|
377
|
+
}
|
|
378
|
+
if (options.progressKey) {
|
|
379
|
+
const key = options.progressKey(value);
|
|
380
|
+
if (key !== lastKey) {
|
|
381
|
+
lastKey = key;
|
|
382
|
+
movedAt = Date.now();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (Date.now() - movedAt > options.timeoutMs) {
|
|
386
|
+
return { settled: false, value };
|
|
387
|
+
}
|
|
388
|
+
if (options.describe) {
|
|
389
|
+
options.onProgress?.(options.describe(value, start2));
|
|
390
|
+
}
|
|
391
|
+
await sleep(options.pollMs);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
function elapsedSeconds(start2) {
|
|
395
|
+
return Math.round((Date.now() - start2) / 1e3);
|
|
396
|
+
}
|
|
397
|
+
function timedOut(timeoutMs, still) {
|
|
398
|
+
return `Timed out after ${Math.round(timeoutMs / 1e3)}s ${still}`;
|
|
399
|
+
}
|
|
400
|
+
|
|
345
401
|
// src/output.ts
|
|
346
402
|
var PRETTY = process.stdout.isTTY === true;
|
|
347
403
|
function out(data) {
|
|
@@ -352,6 +408,31 @@ function progress(message) {
|
|
|
352
408
|
process.stderr.write(`${message}
|
|
353
409
|
`);
|
|
354
410
|
}
|
|
411
|
+
function describeEta(eta, now = Date.now()) {
|
|
412
|
+
if (!eta) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
const minutes = Math.max(1, Math.round((Date.parse(eta) - now) / 6e4));
|
|
416
|
+
if (minutes < 90) {
|
|
417
|
+
return `about ${minutes} min left`;
|
|
418
|
+
}
|
|
419
|
+
const hours = Math.round(minutes / 60 * 10) / 10;
|
|
420
|
+
return `about ${hours} h left`;
|
|
421
|
+
}
|
|
422
|
+
function renderProgress(p, start2, extra) {
|
|
423
|
+
const count = p.total !== null ? `${p.done.toLocaleString()}/${p.total.toLocaleString()} ${p.unit}` : p.done > 0 ? `${p.done.toLocaleString()} ${p.unit}` : null;
|
|
424
|
+
const rate = p.ratePerMinute !== null && p.ratePerMinute > 0 ? `${Math.round(p.ratePerMinute).toLocaleString()}/min` : null;
|
|
425
|
+
const parts = [
|
|
426
|
+
`${p.phase}\u2026`,
|
|
427
|
+
count,
|
|
428
|
+
rate,
|
|
429
|
+
describeEta(p.etaAt),
|
|
430
|
+
extra ?? null,
|
|
431
|
+
p.stalled ? "no progress for 30 min" : null
|
|
432
|
+
].filter((part) => Boolean(part));
|
|
433
|
+
const elapsed = start2 !== void 0 ? ` (${elapsedSeconds(start2)}s)` : "";
|
|
434
|
+
return `${parts.join(" \xB7 ")}${elapsed}`;
|
|
435
|
+
}
|
|
355
436
|
|
|
356
437
|
// src/commands/requests.ts
|
|
357
438
|
var requestsSpecs = {
|
|
@@ -866,11 +947,6 @@ import { execFileSync } from "child_process";
|
|
|
866
947
|
// src/config.ts
|
|
867
948
|
var WORKSPACE_DIR = process.env["WORKSPACE_DIR"] || "/home/vercel-sandbox/workspace";
|
|
868
949
|
|
|
869
|
-
// src/sleep.ts
|
|
870
|
-
function sleep(ms) {
|
|
871
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
872
|
-
}
|
|
873
|
-
|
|
874
950
|
// src/ops/releases.ts
|
|
875
951
|
function list3(ctx, params = {}) {
|
|
876
952
|
return call(
|
|
@@ -2874,50 +2950,6 @@ import path5 from "path";
|
|
|
2874
2950
|
|
|
2875
2951
|
// src/ops/dataSources.ts
|
|
2876
2952
|
import { createHash as createHash2 } from "crypto";
|
|
2877
|
-
|
|
2878
|
-
// src/poll.ts
|
|
2879
|
-
async function pollUntil(read, isSettled, options) {
|
|
2880
|
-
const start2 = Date.now();
|
|
2881
|
-
let transientSince = null;
|
|
2882
|
-
while (true) {
|
|
2883
|
-
let value;
|
|
2884
|
-
try {
|
|
2885
|
-
value = await read();
|
|
2886
|
-
transientSince = null;
|
|
2887
|
-
} catch (err) {
|
|
2888
|
-
if (!isTransientError(err)) {
|
|
2889
|
-
throw err;
|
|
2890
|
-
}
|
|
2891
|
-
transientSince ??= Date.now();
|
|
2892
|
-
if (Date.now() - transientSince > TRANSIENT_GRACE_MS) {
|
|
2893
|
-
throw err;
|
|
2894
|
-
}
|
|
2895
|
-
options.onProgress?.(
|
|
2896
|
-
`retrying after a gateway error\u2026 (${elapsedSeconds(start2)}s)`
|
|
2897
|
-
);
|
|
2898
|
-
await sleep(options.pollMs);
|
|
2899
|
-
continue;
|
|
2900
|
-
}
|
|
2901
|
-
if (isSettled(value)) {
|
|
2902
|
-
return { settled: true, value };
|
|
2903
|
-
}
|
|
2904
|
-
if (Date.now() - start2 > options.timeoutMs) {
|
|
2905
|
-
return { settled: false, value };
|
|
2906
|
-
}
|
|
2907
|
-
if (options.describe) {
|
|
2908
|
-
options.onProgress?.(options.describe(value, start2));
|
|
2909
|
-
}
|
|
2910
|
-
await sleep(options.pollMs);
|
|
2911
|
-
}
|
|
2912
|
-
}
|
|
2913
|
-
function elapsedSeconds(start2) {
|
|
2914
|
-
return Math.round((Date.now() - start2) / 1e3);
|
|
2915
|
-
}
|
|
2916
|
-
function timedOut(timeoutMs, still) {
|
|
2917
|
-
return `Timed out after ${Math.round(timeoutMs / 1e3)}s ${still}`;
|
|
2918
|
-
}
|
|
2919
|
-
|
|
2920
|
-
// src/ops/dataSources.ts
|
|
2921
2953
|
var DEFAULT_WAIT_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
2922
2954
|
var POLL_MS2 = 3e3;
|
|
2923
2955
|
function base(appId) {
|
|
@@ -2998,6 +3030,7 @@ async function waitForIngest(ctx, params) {
|
|
|
2998
3030
|
timeoutMs,
|
|
2999
3031
|
pollMs: POLL_MS2,
|
|
3000
3032
|
describe: (tracked2, start2) => `ingesting\u2026 ${tracked2.length - pendingOf(tracked2).length}/${tracked2.length} done (${elapsedSeconds(start2)}s)`,
|
|
3033
|
+
progressKey: (tracked2) => pendingOf(tracked2).length,
|
|
3001
3034
|
onProgress
|
|
3002
3035
|
}
|
|
3003
3036
|
);
|
|
@@ -3034,6 +3067,7 @@ async function waitForCandidate(ctx, params) {
|
|
|
3034
3067
|
timeoutMs,
|
|
3035
3068
|
pollMs: POLL_MS2,
|
|
3036
3069
|
describe: (progress2, start2) => progress2 ? `rebuilding\u2026 ${progress2.done}/${progress2.total} done (${elapsedSeconds(start2)}s)` : `rebuilding\u2026 (${elapsedSeconds(start2)}s)`,
|
|
3070
|
+
progressKey: (progress2) => progress2?.processing ?? null,
|
|
3037
3071
|
onProgress: params.onProgress
|
|
3038
3072
|
}
|
|
3039
3073
|
);
|
|
@@ -3186,7 +3220,10 @@ async function waitForMove(ctx, params) {
|
|
|
3186
3220
|
{
|
|
3187
3221
|
timeoutMs,
|
|
3188
3222
|
pollMs: POLL_MS2,
|
|
3189
|
-
describe: (source2, start2) =>
|
|
3223
|
+
describe: (source2, start2) => renderProgress(source2.migration.progress, start2),
|
|
3224
|
+
// A corpus of any size moves as long as it keeps moving; the timeout
|
|
3225
|
+
// bounds silence.
|
|
3226
|
+
progressKey: (source2) => source2.migration?.copied ?? null,
|
|
3190
3227
|
onProgress: params.onProgress
|
|
3191
3228
|
}
|
|
3192
3229
|
);
|
|
@@ -3354,6 +3391,13 @@ function resume(ctx, params) {
|
|
|
3354
3391
|
controlBody(params)
|
|
3355
3392
|
);
|
|
3356
3393
|
}
|
|
3394
|
+
function retry(ctx, params) {
|
|
3395
|
+
return call(
|
|
3396
|
+
ctx,
|
|
3397
|
+
"POST",
|
|
3398
|
+
`${base2(ctx.appId)}/${encodeURIComponent(params.id)}/retry`
|
|
3399
|
+
);
|
|
3400
|
+
}
|
|
3357
3401
|
function cancel(ctx, params) {
|
|
3358
3402
|
return call(
|
|
3359
3403
|
ctx,
|
|
@@ -3380,6 +3424,9 @@ async function settle(ctx, params, isSettled) {
|
|
|
3380
3424
|
timeoutMs,
|
|
3381
3425
|
pollMs: POLL_MS3,
|
|
3382
3426
|
describe: describeProgress,
|
|
3427
|
+
// A load of any length is waited out while it moves; the timeout bounds
|
|
3428
|
+
// silence. Planning moves by objects listed, a run by documents.
|
|
3429
|
+
progressKey: (job2) => `${job2.state}:${job2.progress.done}`,
|
|
3383
3430
|
onProgress: params.onProgress
|
|
3384
3431
|
}
|
|
3385
3432
|
);
|
|
@@ -3415,14 +3462,15 @@ async function settle(ctx, params, isSettled) {
|
|
|
3415
3462
|
return { status: "done", job };
|
|
3416
3463
|
}
|
|
3417
3464
|
function describeProgress(job, start2) {
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3465
|
+
if (job.state === "planning" && job.enumerationDone) {
|
|
3466
|
+
return renderProgress(
|
|
3467
|
+
{ ...job.progress, phase: "planning" },
|
|
3468
|
+
start2,
|
|
3469
|
+
`reading a sample of ${job.counts.objectsSeen.toLocaleString()} objects`
|
|
3470
|
+
);
|
|
3421
3471
|
}
|
|
3422
|
-
const
|
|
3423
|
-
|
|
3424
|
-
const spend = `$${job.estimatedDollars.toFixed(2)}${job.budgetDollars !== null ? ` of $${job.budgetDollars.toFixed(2)}` : ""}`;
|
|
3425
|
-
return `${job.state}\u2026 ${processed.toLocaleString()}/${total.toLocaleString()} documents \xB7 ${spend} ${elapsed}`;
|
|
3472
|
+
const spend = job.state === "planning" ? null : `$${job.estimatedDollars.toFixed(2)}${job.budgetDollars !== null ? ` of $${job.budgetDollars.toFixed(2)}` : ""}`;
|
|
3473
|
+
return renderProgress(job.progress, start2, spend);
|
|
3426
3474
|
}
|
|
3427
3475
|
|
|
3428
3476
|
// src/commands/_shared/dataSources.ts
|
|
@@ -3690,7 +3738,7 @@ function hydrate(ctx, params) {
|
|
|
3690
3738
|
ctx,
|
|
3691
3739
|
"POST",
|
|
3692
3740
|
`${base4(ctx.appId)}/hydrate`,
|
|
3693
|
-
{ slug: params.slug
|
|
3741
|
+
{ slug: params.slug }
|
|
3694
3742
|
);
|
|
3695
3743
|
}
|
|
3696
3744
|
function reindex(ctx, params) {
|
|
@@ -3716,7 +3764,10 @@ async function waitForHydration(ctx, params) {
|
|
|
3716
3764
|
{
|
|
3717
3765
|
timeoutMs,
|
|
3718
3766
|
pollMs: POLL_MS4,
|
|
3719
|
-
describe: (source2, start2) =>
|
|
3767
|
+
describe: (source2, start2) => renderProgress(source2.hydration.progress, start2),
|
|
3768
|
+
// A reload of any size is waited out while it moves; the timeout
|
|
3769
|
+
// bounds silence.
|
|
3770
|
+
progressKey: (source2) => source2.hydration?.copied ?? null,
|
|
3720
3771
|
onProgress: params.onProgress
|
|
3721
3772
|
}
|
|
3722
3773
|
);
|
|
@@ -3904,10 +3955,9 @@ async function waitForSet(ctx, params) {
|
|
|
3904
3955
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3905
3956
|
var dataSourceEvalsSpecs = {
|
|
3906
3957
|
"datasources hydrate": {
|
|
3907
|
-
usage: "Usage: remy-admin datasources hydrate [--source <slug>] [--
|
|
3958
|
+
usage: "Usage: remy-admin datasources hydrate [--source <slug>] [--wait] [--timeout <sec>]",
|
|
3908
3959
|
flags: {
|
|
3909
3960
|
source: { type: "string" },
|
|
3910
|
-
since: { type: "string" },
|
|
3911
3961
|
wait: { type: "boolean" },
|
|
3912
3962
|
timeout: { type: "string" }
|
|
3913
3963
|
}
|
|
@@ -4078,14 +4128,7 @@ function selectorFromFlag(raw) {
|
|
|
4078
4128
|
}
|
|
4079
4129
|
async function hydrate2(ctx, a) {
|
|
4080
4130
|
const slug = a.str("source") || DEFAULT_SOURCE;
|
|
4081
|
-
const
|
|
4082
|
-
if (since && Number.isNaN(Date.parse(since))) {
|
|
4083
|
-
fatal("--since must be an ISO 8601 timestamp, e.g. 2026-09-08T15:17:00Z.");
|
|
4084
|
-
}
|
|
4085
|
-
const started = await hydrate(ctx, {
|
|
4086
|
-
slug,
|
|
4087
|
-
...since ? { since: new Date(since).toISOString() } : {}
|
|
4088
|
-
});
|
|
4131
|
+
const started = await hydrate(ctx, { slug });
|
|
4089
4132
|
if (started.resident || !a.bool("wait")) {
|
|
4090
4133
|
out({
|
|
4091
4134
|
dataSource: slug,
|
|
@@ -4380,7 +4423,7 @@ var dataSourceEvalsHandlers = {
|
|
|
4380
4423
|
};
|
|
4381
4424
|
var dataSourceEvalsHelp = `
|
|
4382
4425
|
Warming and sampling:
|
|
4383
|
-
remy-admin datasources hydrate [--source <slug>] [--
|
|
4426
|
+
remy-admin datasources hydrate [--source <slug>] [--wait]
|
|
4384
4427
|
remy-admin datasources sample --source <slug> --size <n> [--as <slug>] [--filter <k=v,...|json>] [--stratify <key>] [--placement <id|shared>] [--wait]
|
|
4385
4428
|
|
|
4386
4429
|
A large source whose index was evicted (the shared pool holds a working set,
|
|
@@ -4388,15 +4431,9 @@ Warming and sampling:
|
|
|
4388
4431
|
background; small sources reload inside the search and never show it.
|
|
4389
4432
|
\`hydrate\` starts that reload ahead of time \u2014 before a demo, say \u2014 and
|
|
4390
4433
|
\`--wait\` blocks until the index is back. \`datasources list\` shows the
|
|
4391
|
-
reload's progress under \`hydration\`.
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
document built at or after that time into the index whether or not the index
|
|
4395
|
-
is resident. Dedicated capacity that restored from a snapshot is missing
|
|
4396
|
-
everything written after the snapshot was taken; the platform starts this
|
|
4397
|
-
refill itself when it sees the restore, and \`infra logs\` shows it. Use the
|
|
4398
|
-
flag for a restore that predates that, with the snapshot's time from the
|
|
4399
|
-
resource log.
|
|
4434
|
+
reload's progress under \`hydration\`. The same reload is what dedicated
|
|
4435
|
+
capacity runs on its own after a lost node or a resume; \`infra logs\` shows
|
|
4436
|
+
it start, and the source's \`hydration\` shows it land.
|
|
4400
4437
|
|
|
4401
4438
|
\`sample\` draws documents from a source into a new one that shares its
|
|
4402
4439
|
exact pinned config, so what you measure on the sample says something about
|
|
@@ -4512,6 +4549,14 @@ var dataSourceJobsSpecs = {
|
|
|
4512
4549
|
timeout: { type: "string" }
|
|
4513
4550
|
}
|
|
4514
4551
|
},
|
|
4552
|
+
"datasources jobs retry": {
|
|
4553
|
+
usage: "Usage: remy-admin datasources jobs retry <id> [--wait] [--timeout <sec>]",
|
|
4554
|
+
positionals: [{ name: "id", required: true }],
|
|
4555
|
+
flags: {
|
|
4556
|
+
wait: { type: "boolean" },
|
|
4557
|
+
timeout: { type: "string" }
|
|
4558
|
+
}
|
|
4559
|
+
},
|
|
4515
4560
|
"datasources jobs cancel": {
|
|
4516
4561
|
usage: "Usage: remy-admin datasources jobs cancel <id>",
|
|
4517
4562
|
positionals: [{ name: "id", required: true }]
|
|
@@ -4620,6 +4665,15 @@ async function jobsResume(ctx, a) {
|
|
|
4620
4665
|
}
|
|
4621
4666
|
await waitAndReport(ctx, a, id, "job", { action: "resume" });
|
|
4622
4667
|
}
|
|
4668
|
+
async function jobsRetry(ctx, a) {
|
|
4669
|
+
const id = a.req("id");
|
|
4670
|
+
const { job } = await retry(ctx, { id });
|
|
4671
|
+
if (!a.bool("wait")) {
|
|
4672
|
+
out({ job });
|
|
4673
|
+
return;
|
|
4674
|
+
}
|
|
4675
|
+
await waitAndReport(ctx, a, id, "job", { action: "retry" });
|
|
4676
|
+
}
|
|
4623
4677
|
async function jobsCancel(ctx, a) {
|
|
4624
4678
|
out(await cancel(ctx, { id: a.req("id") }));
|
|
4625
4679
|
}
|
|
@@ -4630,6 +4684,7 @@ var dataSourceJobsHandlers = {
|
|
|
4630
4684
|
"datasources jobs approve": jobsApprove,
|
|
4631
4685
|
"datasources jobs pause": jobsPause,
|
|
4632
4686
|
"datasources jobs resume": jobsResume,
|
|
4687
|
+
"datasources jobs retry": jobsRetry,
|
|
4633
4688
|
"datasources jobs cancel": jobsCancel
|
|
4634
4689
|
};
|
|
4635
4690
|
var dataSourceJobsHelp = `
|
|
@@ -4640,6 +4695,7 @@ Bulk ingestion (jobs):
|
|
|
4640
4695
|
remy-admin datasources jobs status <id> [--wait] [--timeout <sec>]
|
|
4641
4696
|
remy-admin datasources jobs approve <id> [--wait] [--timeout <sec>]
|
|
4642
4697
|
remy-admin datasources jobs pause|resume|cancel <id>
|
|
4698
|
+
remy-admin datasources jobs retry <id> [--wait] [--timeout <sec>]
|
|
4643
4699
|
|
|
4644
4700
|
A job loads a whole corpus at once. It reads either every object under a
|
|
4645
4701
|
prefix of one of the app's file stores (\`files put\` fills one; an app can
|
|
@@ -4677,6 +4733,14 @@ Bulk ingestion (jobs):
|
|
|
4677
4733
|
from the checkpoint and retries failed batches; \`jobs cancel\` stops it and
|
|
4678
4734
|
keeps what was indexed. Search works on the partial corpus throughout.
|
|
4679
4735
|
|
|
4736
|
+
A batch that fails five times stays failed and the job finishes without it,
|
|
4737
|
+
with its documents left mid-build; \`jobs status\` shows the batch's error.
|
|
4738
|
+
Once the cause is fixed (capacity that was restoring, a provider outage),
|
|
4739
|
+
\`jobs retry <id>\` puts the job back to running over just those batches and
|
|
4740
|
+
finishes it again. A source with documents mid-build refuses to move or
|
|
4741
|
+
re-vectorize (data_source_busy) until they finish, so retry is what clears
|
|
4742
|
+
that.
|
|
4743
|
+
|
|
4680
4744
|
One bulk operation per source: a job refuses to start during a move or while
|
|
4681
4745
|
a candidate version exists, and moves, re-vectorizes and deletes refuse while
|
|
4682
4746
|
a job is in flight (data_source_busy). Interactive \`add\` keeps working.
|
|
@@ -7643,7 +7707,14 @@ async function waitForPhase(ctx, params) {
|
|
|
7643
7707
|
{
|
|
7644
7708
|
timeoutMs,
|
|
7645
7709
|
pollMs: POLL_MS5,
|
|
7646
|
-
describe: (resource2, start2) =>
|
|
7710
|
+
describe: (resource2, start2) => resource2.progress ? renderProgress(
|
|
7711
|
+
resource2.progress,
|
|
7712
|
+
start2,
|
|
7713
|
+
resource2.resizingTo ? `resizing to ${resource2.resizingTo.label}` : null
|
|
7714
|
+
) : `${resource2.phase}${resource2.detail ? ` \xB7 ${resource2.detail}` : ""}${resource2.resizingTo ? ` \xB7 resizing to ${resource2.resizingTo.label}` : ""}\u2026 (${elapsedSeconds(start2)}s)`,
|
|
7715
|
+
// A rebuild after a resume runs as long as it must; the timeout bounds
|
|
7716
|
+
// silence, and a phase or step change counts as movement.
|
|
7717
|
+
progressKey: (resource2) => `${resource2.phase}:${resource2.progress?.done ?? ""}:${resource2.detail ?? ""}`,
|
|
7647
7718
|
onProgress: params.onProgress
|
|
7648
7719
|
}
|
|
7649
7720
|
);
|
|
@@ -7929,26 +8000,29 @@ Placing a data source on a resource:
|
|
|
7929
8000
|
|
|
7930
8001
|
Searches on a source whose resource is not active fail with
|
|
7931
8002
|
capacity_<phase>: capacity_hibernated once parked, capacity_hibernating /
|
|
7932
|
-
capacity_resuming while it moves.
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
user; the stable code
|
|
8003
|
+
capacity_resuming while it moves. Once active, a source whose index is being
|
|
8004
|
+
rebuilt from durable storage (after a resume, a resize or a lost node)
|
|
8005
|
+
answers index_warming with the rebuild's progress and ETA until it lands;
|
|
8006
|
+
\`datasources list\` shows it under hydration and the resource under
|
|
8007
|
+
progress. The messages are written for the app's end user; the stable code
|
|
8008
|
+
is what to act on.
|
|
7937
8009
|
|
|
7938
8010
|
Resizing:
|
|
7939
|
-
A resize keeps the
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
8011
|
+
A resize keeps the documents: the resource is parked, its spec is swapped,
|
|
8012
|
+
and it comes back up with its sources' indexes rebuilt from durable storage
|
|
8013
|
+
in the background (nothing is re-embedded). Searches on those sources answer
|
|
8014
|
+
index_warming until the rebuild lands. A hibernated resource swaps in place
|
|
8015
|
+
and stays parked. Growing needs a month's credits at the new rate; shrinking
|
|
8016
|
+
is refused below what the resource holds (resize_too_small). \`infra get\`
|
|
8017
|
+
shows resizingTo until the swap has happened.
|
|
7945
8018
|
|
|
7946
8019
|
Phases and timing:
|
|
7947
8020
|
requested \u2192 provisioning \u2192 active \u21C4 hibernated \u2192 destroyed, with hibernating /
|
|
7948
8021
|
resuming / decommissioning in between and failed when a change cannot complete
|
|
7949
|
-
(retried automatically; resume or hibernate to retry by hand).
|
|
7950
|
-
takes
|
|
7951
|
-
with
|
|
8022
|
+
(retried automatically; resume or hibernate to retry by hand). A transition
|
|
8023
|
+
takes a minute or two; the rebuild that follows a resume runs under its own
|
|
8024
|
+
progress with a measured ETA. --wait gives up only after --timeout (default
|
|
8025
|
+
600s) WITHOUT movement, so a long rebuild is waited out while it moves.
|
|
7952
8026
|
|
|
7953
8027
|
Billing and the log:
|
|
7954
8028
|
\`infra get\` reports resource.billing: what the resource has actually been
|
|
@@ -7957,7 +8031,8 @@ Billing and the log:
|
|
|
7957
8031
|
|
|
7958
8032
|
The log is the platform's narration of the resource, not the instance's
|
|
7959
8033
|
stdout: each step a transition went through ("Waiting for capacity",
|
|
7960
|
-
"
|
|
8034
|
+
"Rebuilding archive v1 from its artifacts: 14,333,673 document(s)"), each
|
|
8035
|
+
failed attempt, and each failure with the
|
|
7961
8036
|
pod's recent Kubernetes events and the warnings-and-errors tail of the
|
|
7962
8037
|
instance log at that moment (line.data). \`infra get\` includes the newest
|
|
7963
8038
|
200 lines; \`infra logs\` pages the rest and, with --follow, prints new lines
|