@camstack/system 1.2.424 → 1.2.426
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/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-databases.d.ts +51 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +19 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +268 -17
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +268 -17
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +23 -3
- package/dist/builtins/backup-orchestrator/run-queue.d.ts +3 -0
- package/dist/builtins/backup-orchestrator/schedule-store.d.ts +7 -1
- package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +34 -0
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
- package/dist/builtins/local-network/address-book.d.ts +21 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +6 -0
- package/dist/builtins/local-network/local-network.addon.js +48 -7
- package/dist/builtins/local-network/local-network.addon.mjs +48 -7
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/database-snapshot-provider.d.ts +18 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +49 -7
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +49 -7
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-backup/system-backup.service.d.ts +48 -15
- package/dist/builtins/system-config/system-config.addon.js +2 -2
- package/dist/builtins/system-config/system-config.addon.mjs +2 -2
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-BWNs-ZeH.js → composition-sources-60tuHQ9N.js} +1 -1
- package/dist/{composition-sources-tRG7nKWK.mjs → composition-sources-gxVpghXh.mjs} +1 -1
- package/dist/{constants-DHhhVjkt.mjs → constants-B6YTf0v2.mjs} +1 -1
- package/dist/{constants-BBWZlnpQ.js → constants-CO5zpJQY.js} +1 -1
- package/dist/{dist-B-NmfvVC.mjs → dist-CGz9u2HD.mjs} +869 -800
- package/dist/{dist-CiUKtVkX.js → dist-K3WFop9Q.js} +869 -800
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/index.js +272 -198
- package/dist/index.mjs +272 -198
- package/dist/{jwt-signing-key-nwRpRgf_.js → jwt-signing-key-BdDy9ZJN.js} +1 -1
- package/dist/{jwt-signing-key-CUpweD22.mjs → jwt-signing-key-C_w5ielw.mjs} +1 -1
- package/dist/kernel/moleculer/process-service.d.ts +1 -110
- package/dist/kernel/moleculer/runner-heap-flags.d.ts +228 -0
- package/dist/{restore-archive-DA-aJtg7.js → restore-archive-BJp4Llea.js} +156 -65
- package/dist/{restore-archive-CFmPVlWQ.mjs → restore-archive-CZyUM8Qf.mjs} +151 -66
- package/dist/{retired-settings-keys-D62kN_hT.js → retired-settings-keys-Dr2AyhsD.js} +1 -1
- package/dist/{retired-settings-keys-DCGEI4Vi.mjs → retired-settings-keys-Dut6QWh6.mjs} +1 -1
- package/dist/{wal-maintenance-BlqNqaQ3.mjs → wal-maintenance-BZhzoxqA.mjs} +0 -0
- package/dist/{wal-maintenance-BzdCQGjH.js → wal-maintenance-Bzm3O2Nj.js} +0 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as DATABASE_SNAPSHOT_SUFFIX } from "./dist-
|
|
1
|
+
import { g as DATABASE_SNAPSHOT_SUFFIX } from "./dist-CGz9u2HD.mjs";
|
|
2
2
|
import { createCipheriv, createDecipheriv, createHash, createPrivateKey, createPublicKey, diffieHellman, generateKeyPairSync, hkdfSync, randomBytes } from "node:crypto";
|
|
3
3
|
import { Buffer as Buffer$1 } from "buffer";
|
|
4
4
|
import * as fsp from "node:fs/promises";
|
|
@@ -3497,6 +3497,11 @@ function isSqlitePath(relPath) {
|
|
|
3497
3497
|
const db = databaseOfSidecar(relPath) ?? relPath;
|
|
3498
3498
|
return SQLITE_DATABASE_SUFFIXES.some((suffix) => db.endsWith(suffix));
|
|
3499
3499
|
}
|
|
3500
|
+
/**
|
|
3501
|
+
* The databases a run carries when it states none: the minimum (D382). A
|
|
3502
|
+
* schedule, a manual run and `createArchive` all fall back to this one value.
|
|
3503
|
+
*/
|
|
3504
|
+
var DEFAULT_BACKUP_DATABASES = ["settings"];
|
|
3500
3505
|
/** Path of the manifest file embedded inside every archive. */
|
|
3501
3506
|
var ARCHIVE_MANIFEST_NAME = ".camstack-backup-manifest.json";
|
|
3502
3507
|
var DEFAULT_STAT_CACHE_TTL_MS = 6e4;
|
|
@@ -3585,6 +3590,8 @@ var SystemBackupService = class {
|
|
|
3585
3590
|
throwIfCancelled(opts.signal);
|
|
3586
3591
|
const recipient = opts.encryptTo !== void 0 ? parseBackupPublicKey(opts.encryptTo) : null;
|
|
3587
3592
|
const requested = opts.locations ?? DEFAULT_BACKUP_LOCATIONS;
|
|
3593
|
+
const selection = new Set(opts.databases ?? DEFAULT_BACKUP_DATABASES);
|
|
3594
|
+
if (!selection.has("settings")) return this.createSnapshotsOnlyArchive(opts, selection, recipient);
|
|
3588
3595
|
const present = [];
|
|
3589
3596
|
for (const loc of requested) {
|
|
3590
3597
|
const abs = path$1.isAbsolute(loc) ? loc : path$1.join(this.dataDir, loc);
|
|
@@ -3602,7 +3609,12 @@ var SystemBackupService = class {
|
|
|
3602
3609
|
else if (!isExcludedFromBackup(path$1.relative(this.dataDir, abs))) walked.push(toArchiveEntry(abs, this.dataDir, stat));
|
|
3603
3610
|
}
|
|
3604
3611
|
const walkedPaths = new Set(walked.map((e) => e.path));
|
|
3605
|
-
const
|
|
3612
|
+
const ownedById = walked.some((e) => isSqlitePath(e.path)) ? await this.ownedDatabasesInScope(opts.owner, walkedPaths) : /* @__PURE__ */ new Map();
|
|
3613
|
+
const owned = new Set(ownedById.keys());
|
|
3614
|
+
const selected = /* @__PURE__ */ new Map();
|
|
3615
|
+
const omitted = /* @__PURE__ */ new Set();
|
|
3616
|
+
for (const [rel, databaseId] of ownedById) if (selection.has(databaseId)) selected.set(rel, databaseId);
|
|
3617
|
+
else omitted.add(databaseId);
|
|
3606
3618
|
const unowned = /* @__PURE__ */ new Set();
|
|
3607
3619
|
for (const e of walked) {
|
|
3608
3620
|
const db = databaseOfSidecar(e.path);
|
|
@@ -3616,7 +3628,7 @@ var SystemBackupService = class {
|
|
|
3616
3628
|
} });
|
|
3617
3629
|
throw new BackupSnapshotRefusedError(`live SQLite database ${databases.join(", ")} has no owner that can snapshot it — a copy of its files would be torn; remove its stale -wal/-shm/-journal if nothing has it open, or leave its location out of the backup`);
|
|
3618
3630
|
}
|
|
3619
|
-
const
|
|
3631
|
+
const snapshots = selected.size > 0 && opts.owner ? await this.takeOwnerSnapshots(opts.owner, selected, opts.signal) : [];
|
|
3620
3632
|
try {
|
|
3621
3633
|
const liveFiles = /* @__PURE__ */ new Set();
|
|
3622
3634
|
for (const db of owned) {
|
|
@@ -3624,7 +3636,7 @@ var SystemBackupService = class {
|
|
|
3624
3636
|
for (const suffix of SQLITE_SIDECAR_SUFFIXES) liveFiles.add(db + suffix);
|
|
3625
3637
|
}
|
|
3626
3638
|
const entries = walked.filter((e) => !liveFiles.has(e.path));
|
|
3627
|
-
|
|
3639
|
+
for (const snapshot of snapshots) entries.push(snapshot.entry);
|
|
3628
3640
|
const manifest = {
|
|
3629
3641
|
archiveVersion: 1,
|
|
3630
3642
|
createdAt: Date.now(),
|
|
@@ -3633,15 +3645,20 @@ var SystemBackupService = class {
|
|
|
3633
3645
|
entries,
|
|
3634
3646
|
totalBytes: entries.reduce((acc, e) => acc + e.sizeBytes, 0),
|
|
3635
3647
|
totalFiles: entries.filter((e) => e.kind === "file").length,
|
|
3636
|
-
...
|
|
3648
|
+
...snapshots.length > 0 ? { sqliteSnapshots: snapshots.map((snapshot) => snapshot.archived) } : {},
|
|
3649
|
+
...omitted.size > 0 ? { omittedDatabases: [...omitted].toSorted() } : {}
|
|
3637
3650
|
};
|
|
3638
|
-
|
|
3651
|
+
if (omitted.size > 0) this.logger.info("createArchive: owned databases left out of this run", { meta: {
|
|
3652
|
+
omitted: [...omitted].toSorted(),
|
|
3653
|
+
carried: [...selected.values()]
|
|
3654
|
+
} });
|
|
3655
|
+
const carriedSnapshots = new Set(snapshots.map((snapshot) => snapshot.archived.snapshotPath));
|
|
3639
3656
|
return await this.writeArchive({
|
|
3640
3657
|
archivePath: opts.archivePath,
|
|
3641
3658
|
present,
|
|
3642
3659
|
manifest,
|
|
3643
3660
|
excluded: (rel) => {
|
|
3644
|
-
if (rel
|
|
3661
|
+
if (carriedSnapshots.has(rel)) return false;
|
|
3645
3662
|
return liveFiles.has(rel) || isExcludedFromBackup(rel);
|
|
3646
3663
|
},
|
|
3647
3664
|
...opts.signal ? { signal: opts.signal } : {},
|
|
@@ -3655,7 +3672,62 @@ var SystemBackupService = class {
|
|
|
3655
3672
|
}
|
|
3656
3673
|
});
|
|
3657
3674
|
} finally {
|
|
3658
|
-
|
|
3675
|
+
for (const snapshot of snapshots) await this.removeSnapshot(snapshot.absPath);
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
/**
|
|
3679
|
+
* An archive of the selected databases' owner snapshots and the manifest —
|
|
3680
|
+
* no data-root walk, no location, no settings (D852). Refused when the owner
|
|
3681
|
+
* has none of the selected files: an archive of nothing must reach no
|
|
3682
|
+
* destination, because its upload prunes an older archive that has them.
|
|
3683
|
+
*/
|
|
3684
|
+
async createSnapshotsOnlyArchive(opts, selection, recipient) {
|
|
3685
|
+
if (opts.owner === void 0) throw new BackupSnapshotRefusedError("a snapshots-only archive needs the database owner, and none was given");
|
|
3686
|
+
fs$1.mkdirSync(path$1.dirname(opts.archivePath), { recursive: true });
|
|
3687
|
+
const ownedById = await this.ownedDatabasesInScope(opts.owner, null);
|
|
3688
|
+
const selected = /* @__PURE__ */ new Map();
|
|
3689
|
+
for (const [rel, databaseId] of ownedById) if (selection.has(databaseId)) selected.set(rel, databaseId);
|
|
3690
|
+
if (selected.size === 0) {
|
|
3691
|
+
this.logger.warn("createArchive: the owner has none of the selected databases — no archive built", { meta: {
|
|
3692
|
+
requested: [...selection].toSorted(),
|
|
3693
|
+
archivePath: opts.archivePath
|
|
3694
|
+
} });
|
|
3695
|
+
throw new BackupSnapshotRefusedError(`the owner has none of the selected databases (${[...selection].toSorted().join(", ")})`);
|
|
3696
|
+
}
|
|
3697
|
+
const snapshots = await this.takeOwnerSnapshots(opts.owner, selected, opts.signal);
|
|
3698
|
+
try {
|
|
3699
|
+
const entries = snapshots.map((snapshot) => snapshot.entry);
|
|
3700
|
+
const manifest = {
|
|
3701
|
+
archiveVersion: 1,
|
|
3702
|
+
createdAt: Date.now(),
|
|
3703
|
+
dataDir: this.dataDir,
|
|
3704
|
+
locations: [],
|
|
3705
|
+
entries,
|
|
3706
|
+
totalBytes: entries.reduce((acc, e) => acc + e.sizeBytes, 0),
|
|
3707
|
+
totalFiles: entries.length,
|
|
3708
|
+
sqliteSnapshots: snapshots.map((snapshot) => snapshot.archived)
|
|
3709
|
+
};
|
|
3710
|
+
const carried = snapshots.map((snapshot) => snapshot.archived.snapshotPath);
|
|
3711
|
+
const carriedSet = new Set(carried);
|
|
3712
|
+
const result = await this.writeArchive({
|
|
3713
|
+
archivePath: opts.archivePath,
|
|
3714
|
+
present: [],
|
|
3715
|
+
tarRoots: carried,
|
|
3716
|
+
manifest,
|
|
3717
|
+
excluded: (rel) => rel !== ".camstack-backup-manifest.json" && !carriedSet.has(rel),
|
|
3718
|
+
...opts.signal ? { signal: opts.signal } : {},
|
|
3719
|
+
...opts.onArchiveBytes ? { onArchiveBytes: opts.onArchiveBytes } : {},
|
|
3720
|
+
...opts.encryptTo !== void 0 ? { encryptTo: opts.encryptTo } : {}
|
|
3721
|
+
});
|
|
3722
|
+
return recipient === null ? result : {
|
|
3723
|
+
...result,
|
|
3724
|
+
encryption: {
|
|
3725
|
+
scheme: BACKUP_ENCRYPTION_SCHEME,
|
|
3726
|
+
keyId: recipient.keyId
|
|
3727
|
+
}
|
|
3728
|
+
};
|
|
3729
|
+
} finally {
|
|
3730
|
+
for (const snapshot of snapshots) await this.removeSnapshot(snapshot.absPath);
|
|
3659
3731
|
}
|
|
3660
3732
|
}
|
|
3661
3733
|
/**
|
|
@@ -3689,7 +3761,7 @@ var SystemBackupService = class {
|
|
|
3689
3761
|
if (!excludePrefix) return true;
|
|
3690
3762
|
return norm !== excludePrefix && !norm.startsWith(`${excludePrefix}/`);
|
|
3691
3763
|
}
|
|
3692
|
-
}, [ARCHIVE_MANIFEST_NAME, ...present]);
|
|
3764
|
+
}, [ARCHIVE_MANIFEST_NAME, ...opts.tarRoots ?? present]);
|
|
3693
3765
|
const sink = fs$1.createWriteStream(opts.archivePath, { mode: 384 });
|
|
3694
3766
|
try {
|
|
3695
3767
|
const streamOpts = opts.signal ? { signal: opts.signal } : {};
|
|
@@ -3806,12 +3878,13 @@ var SystemBackupService = class {
|
|
|
3806
3878
|
if (fs$1.existsSync(markerPath)) fs$1.rmSync(markerPath, { force: true });
|
|
3807
3879
|
}
|
|
3808
3880
|
/**
|
|
3809
|
-
* The databases the owner declares, archive-relative, that this walk found
|
|
3810
|
-
* One outside this data root is not in scope. An owner
|
|
3811
|
-
* stops the archive: without the answer, nothing says
|
|
3881
|
+
* The databases the owner declares, archive-relative, that this walk found,
|
|
3882
|
+
* with the id of each. One outside this data root is not in scope. An owner
|
|
3883
|
+
* that cannot answer stops the archive: without the answer, nothing says
|
|
3884
|
+
* which file is live.
|
|
3812
3885
|
*/
|
|
3813
3886
|
async ownedDatabasesInScope(owner, walked) {
|
|
3814
|
-
if (owner === void 0) return /* @__PURE__ */ new
|
|
3887
|
+
if (owner === void 0) return /* @__PURE__ */ new Map();
|
|
3815
3888
|
let declared;
|
|
3816
3889
|
try {
|
|
3817
3890
|
declared = await owner.listDatabases();
|
|
@@ -3820,22 +3893,23 @@ var SystemBackupService = class {
|
|
|
3820
3893
|
this.logger.error("createArchive: the database owner did not say what it owns — no archive built", { meta: { error: reason } });
|
|
3821
3894
|
throw new BackupSnapshotRefusedError(`the database owner could not be asked: ${reason}`);
|
|
3822
3895
|
}
|
|
3823
|
-
const inScope = /* @__PURE__ */ new
|
|
3824
|
-
for (const
|
|
3825
|
-
const rel = this.archiveRelative(
|
|
3826
|
-
if (rel !== null && walked.has(rel)) inScope.
|
|
3896
|
+
const inScope = /* @__PURE__ */ new Map();
|
|
3897
|
+
for (const db of declared) {
|
|
3898
|
+
const rel = this.archiveRelative(db.livePath);
|
|
3899
|
+
if (rel !== null && (walked === null || walked.has(rel))) inScope.set(rel, db.databaseId);
|
|
3827
3900
|
}
|
|
3828
3901
|
return inScope;
|
|
3829
3902
|
}
|
|
3830
3903
|
/**
|
|
3831
|
-
* Ask the owner for
|
|
3832
|
-
*
|
|
3833
|
-
*
|
|
3834
|
-
*
|
|
3835
|
-
* database
|
|
3904
|
+
* Ask the owner for one verified snapshot per SELECTED database, one after
|
|
3905
|
+
* the other, and place each in this archive. A snapshot must sit on THIS data
|
|
3906
|
+
* root — the call is pinned to this node, so a path elsewhere means it
|
|
3907
|
+
* reached another host, and that file is not ours to read — beside the very
|
|
3908
|
+
* database it was asked for. Anything else is refused, and the run builds
|
|
3909
|
+
* nothing: the copies already taken are removed.
|
|
3836
3910
|
*
|
|
3837
|
-
* Only ever DELETED here: `<
|
|
3838
|
-
* a name this process derives itself. A path the owner ANSWERS is never
|
|
3911
|
+
* Only ever DELETED here: `<selected db>.backup-snapshot` under this data
|
|
3912
|
+
* root, a name this process derives itself. A path the owner ANSWERS is never
|
|
3839
3913
|
* deleted on its word — answering the live database as the snapshot would
|
|
3840
3914
|
* otherwise delete the live database. A file at any other path is left to
|
|
3841
3915
|
* the owner's own sweep.
|
|
@@ -3843,62 +3917,73 @@ var SystemBackupService = class {
|
|
|
3843
3917
|
* A cancel is honoured while the owner is still copying; the copy it may
|
|
3844
3918
|
* finish afterwards is removed when that call settles.
|
|
3845
3919
|
*/
|
|
3846
|
-
async
|
|
3920
|
+
async takeOwnerSnapshots(owner, selected, signal) {
|
|
3847
3921
|
const removeOwnedSnapshots = async () => {
|
|
3848
|
-
for (const db of
|
|
3922
|
+
for (const db of selected.keys()) await this.removeSnapshot(path$1.join(this.dataDir, db + DATABASE_SNAPSHOT_SUFFIX));
|
|
3849
3923
|
};
|
|
3924
|
+
const taken = [];
|
|
3925
|
+
try {
|
|
3926
|
+
for (const [expectedLive, databaseId] of selected) {
|
|
3927
|
+
throwIfCancelled(signal);
|
|
3928
|
+
taken.push(await this.takeOneSnapshot(owner, databaseId, expectedLive, signal, selected, removeOwnedSnapshots));
|
|
3929
|
+
}
|
|
3930
|
+
} catch (err) {
|
|
3931
|
+
await removeOwnedSnapshots();
|
|
3932
|
+
throw err;
|
|
3933
|
+
}
|
|
3934
|
+
return taken;
|
|
3935
|
+
}
|
|
3936
|
+
async takeOneSnapshot(owner, databaseId, expectedLive, signal, selected, removeOwnedSnapshots) {
|
|
3850
3937
|
let result;
|
|
3851
3938
|
try {
|
|
3852
|
-
result = await raceAbort(owner.writeSnapshot(), signal, () => {
|
|
3853
|
-
this.logger.info("createArchive: run cancelled while the owner copied — its copy is removed when it lands", { meta: {
|
|
3939
|
+
result = await raceAbort(owner.writeSnapshot(databaseId), signal, () => {
|
|
3940
|
+
this.logger.info("createArchive: run cancelled while the owner copied — its copy is removed when it lands", { meta: {
|
|
3941
|
+
databases: [...selected.values()],
|
|
3942
|
+
database: databaseId
|
|
3943
|
+
} });
|
|
3854
3944
|
return removeOwnedSnapshots();
|
|
3855
3945
|
});
|
|
3856
3946
|
} catch (err) {
|
|
3857
3947
|
if (err instanceof BackupCancelledError) throw err;
|
|
3858
3948
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3859
3949
|
this.logger.error("createArchive: the owner could not snapshot its live database — no archive built", { meta: {
|
|
3860
|
-
databases: [...
|
|
3950
|
+
databases: [...selected.values()],
|
|
3951
|
+
database: databaseId,
|
|
3861
3952
|
error: reason
|
|
3862
3953
|
} });
|
|
3863
|
-
|
|
3864
|
-
throw new BackupSnapshotRefusedError(reason);
|
|
3954
|
+
throw new BackupSnapshotRefusedError(`${databaseId}: ${reason}`);
|
|
3865
3955
|
}
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
dataDir: this.dataDir
|
|
3873
|
-
} });
|
|
3874
|
-
throw new BackupSnapshotRefusedError(`snapshot ${result.snapshotPath} is not under this archive's data root ${this.dataDir}`);
|
|
3875
|
-
}
|
|
3876
|
-
if (snapshotPath !== livePath + ".backup-snapshot") throw new BackupSnapshotRefusedError(`snapshot ${snapshotPath} does not sit beside the database ${livePath} it copies`);
|
|
3877
|
-
const uncovered = [...owned].filter((db) => db !== livePath);
|
|
3878
|
-
if (!owned.has(livePath) || uncovered.length > 0) throw new BackupSnapshotRefusedError(`snapshot copies ${livePath}, but the owned database(s) in this archive are ${[...owned].join(", ")}`);
|
|
3879
|
-
const absPath = path$1.join(this.dataDir, snapshotPath);
|
|
3880
|
-
const stat = await fsp.stat(absPath);
|
|
3881
|
-
this.logger.info("createArchive: carrying the owner snapshot in place of the live database", { meta: {
|
|
3882
|
-
database: livePath,
|
|
3883
|
-
snapshot: snapshotPath,
|
|
3884
|
-
sizeBytes: stat.size,
|
|
3885
|
-
tables: result.tables.length,
|
|
3886
|
-
copyMs: result.copyMs,
|
|
3887
|
-
verifyMs: result.verifyMs
|
|
3956
|
+
const livePath = this.archiveRelative(result.livePath);
|
|
3957
|
+
const snapshotPath = this.archiveRelative(result.snapshotPath);
|
|
3958
|
+
if (livePath === null || snapshotPath === null) {
|
|
3959
|
+
this.logger.warn("createArchive: the owner answered a snapshot outside this data root — not touched, left to its sweep", { meta: {
|
|
3960
|
+
snapshot: result.snapshotPath,
|
|
3961
|
+
dataDir: this.dataDir
|
|
3888
3962
|
} });
|
|
3889
|
-
|
|
3890
|
-
absPath,
|
|
3891
|
-
archived: {
|
|
3892
|
-
...result,
|
|
3893
|
-
livePath,
|
|
3894
|
-
snapshotPath
|
|
3895
|
-
},
|
|
3896
|
-
entry: toArchiveEntry(absPath, this.dataDir, stat)
|
|
3897
|
-
};
|
|
3898
|
-
} catch (err) {
|
|
3899
|
-
await removeOwnedSnapshots();
|
|
3900
|
-
throw err;
|
|
3963
|
+
throw new BackupSnapshotRefusedError(`snapshot ${result.snapshotPath} is not under this archive's data root ${this.dataDir}`);
|
|
3901
3964
|
}
|
|
3965
|
+
if (snapshotPath !== livePath + ".backup-snapshot") throw new BackupSnapshotRefusedError(`snapshot ${snapshotPath} does not sit beside the database ${livePath} it copies`);
|
|
3966
|
+
if (livePath !== expectedLive || result.databaseId !== databaseId) throw new BackupSnapshotRefusedError(`snapshot copies ${livePath} (${result.databaseId}), but ${databaseId} (${expectedLive}) was asked for`);
|
|
3967
|
+
const absPath = path$1.join(this.dataDir, snapshotPath);
|
|
3968
|
+
const stat = await fsp.stat(absPath);
|
|
3969
|
+
this.logger.info("createArchive: carrying the owner snapshot in place of the live database", { meta: {
|
|
3970
|
+
database: livePath,
|
|
3971
|
+
databaseId,
|
|
3972
|
+
snapshot: snapshotPath,
|
|
3973
|
+
sizeBytes: stat.size,
|
|
3974
|
+
tables: result.tables.length,
|
|
3975
|
+
copyMs: result.copyMs,
|
|
3976
|
+
verifyMs: result.verifyMs
|
|
3977
|
+
} });
|
|
3978
|
+
return {
|
|
3979
|
+
absPath,
|
|
3980
|
+
archived: {
|
|
3981
|
+
...result,
|
|
3982
|
+
livePath,
|
|
3983
|
+
snapshotPath
|
|
3984
|
+
},
|
|
3985
|
+
entry: toArchiveEntry(absPath, this.dataDir, stat)
|
|
3986
|
+
};
|
|
3902
3987
|
}
|
|
3903
3988
|
async removeSnapshot(absPath) {
|
|
3904
3989
|
try {
|
|
@@ -4042,4 +4127,4 @@ async function prepareRestoreArchive(input) {
|
|
|
4042
4127
|
}
|
|
4043
4128
|
}
|
|
4044
4129
|
//#endregion
|
|
4045
|
-
export { BackupSnapshotRefusedError as a,
|
|
4130
|
+
export { BackupSnapshotRefusedError as a, BackupDecryptError as c, ENCRYPTED_BACKUP_SUFFIX as d, generateBackupKeyPair as f, readBackupEncryptionHeader as h, BackupCancelledError as i, BackupKeyFormatError as l, parseBackupSecretKey as m, precheckRestoreKey as n, DEFAULT_BACKUP_DATABASES as o, parseBackupPublicKey as p, prepareRestoreArchive as r, SystemBackupService as s, BackupKeyRequiredError as t, BackupKeyMismatchError as u };
|
|
Binary file
|
|
Binary file
|