@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
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as addonPagesCapability, cr as errMsg, lr as BaseAddon, ti as EventCategory } from "../../dist-
|
|
1
|
+
import { G as addonPagesCapability, cr as errMsg, lr as BaseAddon, ti as EventCategory } from "../../dist-CGz9u2HD.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cr as errMsg, lr as BaseAddon, q as addonWidgetsCapability, ti as EventCategory } from "../../dist-
|
|
1
|
+
import { cr as errMsg, lr as BaseAddon, q as addonWidgetsCapability, ti as EventCategory } from "../../dist-CGz9u2HD.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
7
|
//#region src/builtins/alerts/device-label.ts
|
|
8
8
|
/**
|
|
9
9
|
* Operator-facing device label for alert messages.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { J as alertsCapability, Tr as createEvent, cr as errMsg, lr as BaseAddon, n as AlertSchema, ti as EventCategory } from "../../dist-
|
|
1
|
+
import { J as alertsCapability, Tr as createEvent, cr as errMsg, lr as BaseAddon, n as AlertSchema, ti as EventCategory } from "../../dist-CGz9u2HD.mjs";
|
|
2
2
|
//#region src/builtins/alerts/device-label.ts
|
|
3
3
|
/**
|
|
4
4
|
* Operator-facing device label for alert messages.
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
7
|
//#region src/builtins/autotrack/autotrack-config.ts
|
|
8
8
|
var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
|
|
9
9
|
deadZoneFraction: .5,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as FIRST_LEVEL_MACRO_CLASSES, Pr as isEvent, Z as bareAddonId, cr as errMsg, hn as ptzAutotrackCapability, lr as BaseAddon, ti as EventCategory } from "../../dist-
|
|
1
|
+
import { C as FIRST_LEVEL_MACRO_CLASSES, Pr as isEvent, Z as bareAddonId, cr as errMsg, hn as ptzAutotrackCapability, lr as BaseAddon, ti as EventCategory } from "../../dist-CGz9u2HD.mjs";
|
|
2
2
|
//#region src/builtins/autotrack/autotrack-config.ts
|
|
3
3
|
var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
|
|
4
4
|
deadZoneFraction: .5,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which database files a backup carries, and when (D852).
|
|
3
|
+
*
|
|
4
|
+
* Settings is the one a decision reads and runs nightly. Events and history are
|
|
5
|
+
* statistical or ledger stores; losing up to a week costs chart gaps, never
|
|
6
|
+
* configuration, so they ride a WEEKLY schedule whose archive is a consistent
|
|
7
|
+
* full set. Pure functions, no I/O: the orchestrator feeds them what it read.
|
|
8
|
+
*/
|
|
9
|
+
import type { DataStoreDatabase } from "@camstack/types";
|
|
10
|
+
import type { BackupSchedule } from "./schedule-store.js";
|
|
11
|
+
import type { SeedMarkers } from "./seed-marker-store.js";
|
|
12
|
+
/** Stable id of the seeded weekly schedule. */
|
|
13
|
+
export declare const WEEKLY_SCHEDULE_ID = "weekly-events-history";
|
|
14
|
+
export declare const WEEKLY_SCHEDULE_LABEL = "Weekly — events & history";
|
|
15
|
+
/** Sundays 04:00 — an hour after the nightly settings run. */
|
|
16
|
+
export declare const WEEKLY_SCHEDULE_CRON = "0 4 * * 0";
|
|
17
|
+
export declare const WEEKLY_SCHEDULE_RETENTION = 4;
|
|
18
|
+
/**
|
|
19
|
+
* Events and history ONLY: a run that does not select settings carries no
|
|
20
|
+
* data-root walk either, so the weekly archive is just the two snapshots.
|
|
21
|
+
*/
|
|
22
|
+
export declare const WEEKLY_SCHEDULE_DATABASES: readonly DataStoreDatabase[];
|
|
23
|
+
/** What a schedule carries: its own list, else the minimum (D382). */
|
|
24
|
+
export declare function databasesOfSchedule(schedule: Pick<BackupSchedule, "databases">): readonly DataStoreDatabase[];
|
|
25
|
+
/**
|
|
26
|
+
* True when a run asks for a database beyond settings and the owner has none
|
|
27
|
+
* of them open: the run would only repeat the nightly archive. A settings-only
|
|
28
|
+
* run is never nothing-to-carry.
|
|
29
|
+
*/
|
|
30
|
+
export declare function hasNothingBeyondSettings(requested: readonly DataStoreDatabase[], owned: readonly DataStoreDatabase[]): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The weekly schedule to seed, or null. Created only when NO schedule carries
|
|
33
|
+
* `events` (a seed never overwrites, D728 — an operator's own weekly schedule,
|
|
34
|
+
* or an edited seed, is left alone), and only when there is a nightly schedule
|
|
35
|
+
* to take the destinations from: a hub that backs up nowhere gets no weekly
|
|
36
|
+
* archive either.
|
|
37
|
+
*/
|
|
38
|
+
export declare function planWeeklySeed(existing: readonly BackupSchedule[]): BackupSchedule | null;
|
|
39
|
+
/** The slice of the schedule store the seed needs. */
|
|
40
|
+
export interface ScheduleSeedStore {
|
|
41
|
+
list(): Promise<readonly BackupSchedule[]>;
|
|
42
|
+
upsert(schedule: BackupSchedule): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Seed the weekly schedule if {@link planWeeklySeed} says so; returns what it
|
|
46
|
+
* wrote. Exactly once ever: the marker is written after the row, and a marker
|
|
47
|
+
* that exists ends the seed for good — an operator who disabled or deleted the
|
|
48
|
+
* weekly is never second-guessed. A weekly row found with no marker (seeded
|
|
49
|
+
* before the marker existed) is marked, not re-created.
|
|
50
|
+
*/
|
|
51
|
+
export declare function seedWeeklySchedule(store: ScheduleSeedStore, markers: SeedMarkers): Promise<BackupSchedule | null>;
|
|
@@ -249,6 +249,19 @@ export declare class BackupOrchestratorAddon extends BaseAddon<Record<string, ne
|
|
|
249
249
|
*/
|
|
250
250
|
private onScheduleTick;
|
|
251
251
|
/**
|
|
252
|
+
* A schedule that asks for events/history while the owner has neither open
|
|
253
|
+
* would only repeat the nightly archive (D852: the weekly schedule has
|
|
254
|
+
* nothing to carry until those files exist). Said on the record, no archive
|
|
255
|
+
* built, no outcome stamped. An owner that cannot answer never skips: the
|
|
256
|
+
* run goes ahead and fails — or succeeds — in the open.
|
|
257
|
+
*/
|
|
258
|
+
private nothingToCarry;
|
|
259
|
+
/**
|
|
260
|
+
* Seed the weekly "events & history" schedule (D852) — once, and never over
|
|
261
|
+
* anything the operator has: see `planWeeklySeed`.
|
|
262
|
+
*/
|
|
263
|
+
private seedWeekly;
|
|
264
|
+
/**
|
|
252
265
|
* Fire one schedule and RECORD what happened to it, naming every
|
|
253
266
|
* destination. Three outcomes, three different persisted states —
|
|
254
267
|
* because "fired" and "backed up" were the same field until D384:
|
|
@@ -258,6 +271,12 @@ export declare class BackupOrchestratorAddon extends BaseAddon<Record<string, ne
|
|
|
258
271
|
* - the stamp could not be written → logged, named, not swallowed.
|
|
259
272
|
*/
|
|
260
273
|
private runScheduledBackup;
|
|
274
|
+
/**
|
|
275
|
+
* The database files the owner has open right now, for the selection UI. An
|
|
276
|
+
* owner that cannot answer is `answered: false` — never an empty list, which
|
|
277
|
+
* the UI would read as "none exists yet".
|
|
278
|
+
*/
|
|
279
|
+
private listAvailableDatabases;
|
|
261
280
|
private listSchedules;
|
|
262
281
|
private upsertSchedule;
|
|
263
282
|
private deleteSchedule;
|
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
7
|
-
const require_restore_archive = require("../../restore-archive-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
|
+
const require_restore_archive = require("../../restore-archive-BJp4Llea.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_fs_promises = require("node:fs/promises");
|
|
10
10
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -12,6 +12,138 @@ let node_path = require("node:path");
|
|
|
12
12
|
node_path = require_chunk.__toESM(node_path);
|
|
13
13
|
let node_fs = require("node:fs");
|
|
14
14
|
node_fs = require_chunk.__toESM(node_fs);
|
|
15
|
+
//#region src/builtins/backup-orchestrator/backup-databases.ts
|
|
16
|
+
/** Stable id of the seeded weekly schedule. */
|
|
17
|
+
var WEEKLY_SCHEDULE_ID = "weekly-events-history";
|
|
18
|
+
var WEEKLY_SCHEDULE_LABEL = "Weekly — events & history";
|
|
19
|
+
/** Sundays 04:00 — an hour after the nightly settings run. */
|
|
20
|
+
var WEEKLY_SCHEDULE_CRON = "0 4 * * 0";
|
|
21
|
+
/**
|
|
22
|
+
* Events and history ONLY: a run that does not select settings carries no
|
|
23
|
+
* data-root walk either, so the weekly archive is just the two snapshots.
|
|
24
|
+
*/
|
|
25
|
+
var WEEKLY_SCHEDULE_DATABASES = ["events", "history"];
|
|
26
|
+
/** What a schedule carries: its own list, else the minimum (D382). */
|
|
27
|
+
function databasesOfSchedule(schedule) {
|
|
28
|
+
return schedule.databases !== void 0 && schedule.databases.length > 0 ? schedule.databases : require_restore_archive.DEFAULT_BACKUP_DATABASES;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* True when a run asks for a database beyond settings and the owner has none
|
|
32
|
+
* of them open: the run would only repeat the nightly archive. A settings-only
|
|
33
|
+
* run is never nothing-to-carry.
|
|
34
|
+
*/
|
|
35
|
+
function hasNothingBeyondSettings(requested, owned) {
|
|
36
|
+
const extra = requested.filter((id) => id !== "settings");
|
|
37
|
+
if (extra.length === 0) return false;
|
|
38
|
+
return !extra.some((id) => owned.includes(id));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The weekly schedule to seed, or null. Created only when NO schedule carries
|
|
42
|
+
* `events` (a seed never overwrites, D728 — an operator's own weekly schedule,
|
|
43
|
+
* or an edited seed, is left alone), and only when there is a nightly schedule
|
|
44
|
+
* to take the destinations from: a hub that backs up nowhere gets no weekly
|
|
45
|
+
* archive either.
|
|
46
|
+
*/
|
|
47
|
+
function planWeeklySeed(existing) {
|
|
48
|
+
if (existing.some((s) => s.id === "weekly-events-history")) return null;
|
|
49
|
+
if (existing.some((s) => databasesOfSchedule(s).includes("events"))) return null;
|
|
50
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
51
|
+
for (const s of existing) {
|
|
52
|
+
if (!s.enabled) continue;
|
|
53
|
+
for (const id of s.locationIds) destinations.add(id);
|
|
54
|
+
}
|
|
55
|
+
if (destinations.size === 0) return null;
|
|
56
|
+
return {
|
|
57
|
+
id: WEEKLY_SCHEDULE_ID,
|
|
58
|
+
label: WEEKLY_SCHEDULE_LABEL,
|
|
59
|
+
cron: WEEKLY_SCHEDULE_CRON,
|
|
60
|
+
enabled: true,
|
|
61
|
+
locationIds: [...destinations].toSorted(),
|
|
62
|
+
retentionCount: 4,
|
|
63
|
+
databases: WEEKLY_SCHEDULE_DATABASES
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Seed the weekly schedule if {@link planWeeklySeed} says so; returns what it
|
|
68
|
+
* wrote. Exactly once ever: the marker is written after the row, and a marker
|
|
69
|
+
* that exists ends the seed for good — an operator who disabled or deleted the
|
|
70
|
+
* weekly is never second-guessed. A weekly row found with no marker (seeded
|
|
71
|
+
* before the marker existed) is marked, not re-created.
|
|
72
|
+
*/
|
|
73
|
+
async function seedWeeklySchedule(store, markers) {
|
|
74
|
+
if (await markers.has("weekly-events-history")) return null;
|
|
75
|
+
const existing = await store.list();
|
|
76
|
+
if (existing.some((s) => s.id === "weekly-events-history")) {
|
|
77
|
+
await markers.mark(WEEKLY_SCHEDULE_ID);
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const seed = planWeeklySeed(existing);
|
|
81
|
+
if (seed === null) return null;
|
|
82
|
+
await store.upsert(seed);
|
|
83
|
+
await markers.mark(WEEKLY_SCHEDULE_ID);
|
|
84
|
+
return seed;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/builtins/backup-orchestrator/seed-marker-store.ts
|
|
88
|
+
/**
|
|
89
|
+
* @durable class=config owner=backup-orchestrator
|
|
90
|
+
* write="the orchestrator inserts one row per seed id the first time that
|
|
91
|
+
* seed is created (or found already created); never updated"
|
|
92
|
+
* retention="none — one tiny row per seed ever made; deleting it lets the
|
|
93
|
+
* seed be re-created once more on the next boot"
|
|
94
|
+
*/
|
|
95
|
+
var BACKUP_SEED_MARKERS_COLLECTION = "backup_seed_markers";
|
|
96
|
+
var COLUMNS$1 = [{
|
|
97
|
+
name: "seed_id",
|
|
98
|
+
type: "TEXT",
|
|
99
|
+
primaryKey: true
|
|
100
|
+
}, {
|
|
101
|
+
name: "seeded_at",
|
|
102
|
+
type: "INTEGER",
|
|
103
|
+
notNull: true
|
|
104
|
+
}];
|
|
105
|
+
var BackupSeedMarkerStore = class {
|
|
106
|
+
store;
|
|
107
|
+
now;
|
|
108
|
+
declared = false;
|
|
109
|
+
constructor(store, now = Date.now) {
|
|
110
|
+
this.store = store;
|
|
111
|
+
this.now = now;
|
|
112
|
+
}
|
|
113
|
+
async ensureDeclared() {
|
|
114
|
+
if (this.declared) return;
|
|
115
|
+
await this.store.declareCollection({
|
|
116
|
+
collection: BACKUP_SEED_MARKERS_COLLECTION,
|
|
117
|
+
columns: COLUMNS$1
|
|
118
|
+
});
|
|
119
|
+
this.declared = true;
|
|
120
|
+
}
|
|
121
|
+
async has(seedId) {
|
|
122
|
+
await this.ensureDeclared();
|
|
123
|
+
return (await this.store.query({
|
|
124
|
+
collection: BACKUP_SEED_MARKERS_COLLECTION,
|
|
125
|
+
filter: {
|
|
126
|
+
where: { seed_id: seedId },
|
|
127
|
+
limit: 1
|
|
128
|
+
}
|
|
129
|
+
})).length > 0;
|
|
130
|
+
}
|
|
131
|
+
async mark(seedId) {
|
|
132
|
+
await this.ensureDeclared();
|
|
133
|
+
if (await this.has(seedId)) return;
|
|
134
|
+
await this.store.insert({
|
|
135
|
+
collection: BACKUP_SEED_MARKERS_COLLECTION,
|
|
136
|
+
record: {
|
|
137
|
+
id: seedId,
|
|
138
|
+
data: {
|
|
139
|
+
seed_id: seedId,
|
|
140
|
+
seeded_at: this.now()
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
//#endregion
|
|
15
147
|
//#region ../../node_modules/croner/dist/croner.js
|
|
16
148
|
function T(s) {
|
|
17
149
|
return Date.UTC(s.y, s.m - 1, s.d, s.h, s.i, s.s);
|
|
@@ -1277,7 +1409,8 @@ function normalizeManifest(raw) {
|
|
|
1277
1409
|
sizeBytes: Number(cand["sizeBytes"]),
|
|
1278
1410
|
...typeof cand["label"] === "string" ? { label: cand["label"] } : {},
|
|
1279
1411
|
manifest,
|
|
1280
|
-
...encryptionOf(cand["encryption"])
|
|
1412
|
+
...encryptionOf(cand["encryption"]),
|
|
1413
|
+
...databasesOf(cand["databases"])
|
|
1281
1414
|
};
|
|
1282
1415
|
archives.push(entry);
|
|
1283
1416
|
}
|
|
@@ -1290,6 +1423,15 @@ var EMPTY_MANIFEST = {
|
|
|
1290
1423
|
version: 1,
|
|
1291
1424
|
archives: []
|
|
1292
1425
|
};
|
|
1426
|
+
function databasesOf(raw) {
|
|
1427
|
+
if (!Array.isArray(raw)) return {};
|
|
1428
|
+
const known = [];
|
|
1429
|
+
const unknown = [];
|
|
1430
|
+
for (const item of raw) if (item === "settings" || item === "events" || item === "history") known.push(item);
|
|
1431
|
+
else if (typeof item === "string") unknown.push(item);
|
|
1432
|
+
if (known.length > 0) return { databases: known };
|
|
1433
|
+
return unknown.length > 0 ? { unrecognisedDatabases: unknown } : {};
|
|
1434
|
+
}
|
|
1293
1435
|
function encryptionOf(raw) {
|
|
1294
1436
|
if (typeof raw !== "object" || raw === null) return {};
|
|
1295
1437
|
const scheme = Reflect.get(raw, "scheme");
|
|
@@ -1313,7 +1455,8 @@ function outlineOfManifest(manifest) {
|
|
|
1313
1455
|
locations: [...manifest.locations],
|
|
1314
1456
|
entries: [],
|
|
1315
1457
|
totalBytes: manifest.totalBytes,
|
|
1316
|
-
totalFiles: manifest.totalFiles
|
|
1458
|
+
totalFiles: manifest.totalFiles,
|
|
1459
|
+
...manifest.omittedDatabases !== void 0 ? { omittedDatabases: [...manifest.omittedDatabases] } : {}
|
|
1317
1460
|
};
|
|
1318
1461
|
}
|
|
1319
1462
|
/**
|
|
@@ -1329,9 +1472,15 @@ function buildArchiveEntry(input) {
|
|
|
1329
1472
|
sizeBytes: input.sizeBytes,
|
|
1330
1473
|
...input.label !== void 0 ? { label: input.label } : {},
|
|
1331
1474
|
manifest: input.encryption !== void 0 ? outlineOfManifest(input.manifest) : input.manifest,
|
|
1332
|
-
...input.encryption !== void 0 ? { encryption: input.encryption } : {}
|
|
1475
|
+
...input.encryption !== void 0 ? { encryption: input.encryption } : {},
|
|
1476
|
+
...input.databases !== void 0 ? { databases: [...input.databases] } : {}
|
|
1333
1477
|
};
|
|
1334
1478
|
}
|
|
1479
|
+
/** The key under which archives of one cadence prune each other. */
|
|
1480
|
+
function retentionClassOf(entry) {
|
|
1481
|
+
if (entry.databases === void 0 && entry.unrecognisedDatabases !== void 0) return `?${[...entry.unrecognisedDatabases].toSorted().join("+")}`;
|
|
1482
|
+
return [...entry.databases ?? require_restore_archive.DEFAULT_BACKUP_DATABASES].toSorted().join("+");
|
|
1483
|
+
}
|
|
1335
1484
|
/**
|
|
1336
1485
|
* Pure retention split: given an archive list and the operator's
|
|
1337
1486
|
* `retentionCount`, return `{ keep, drop }` where `keep` is the most-
|
|
@@ -1340,20 +1489,27 @@ function buildArchiveEntry(input) {
|
|
|
1340
1489
|
* `retentionCount <= 0` is treated as "no pruning" — defensive against
|
|
1341
1490
|
* a config value that would otherwise wipe every archive on the next
|
|
1342
1491
|
* write.
|
|
1492
|
+
*
|
|
1493
|
+
* `cadence` (see {@link retentionClassOf}) restricts the count to archives of
|
|
1494
|
+
* the run that was just written: nightly archives (settings) and weekly ones
|
|
1495
|
+
* (settings + events + history) are retained separately.
|
|
1343
1496
|
*/
|
|
1344
|
-
function applyRetention(archives, retentionCount) {
|
|
1497
|
+
function applyRetention(archives, retentionCount, cadence) {
|
|
1345
1498
|
if (retentionCount <= 0) return {
|
|
1346
1499
|
keep: archives,
|
|
1347
1500
|
drop: []
|
|
1348
1501
|
};
|
|
1349
1502
|
const sorted = [...archives].toSorted((a, b) => b.createdAt - a.createdAt);
|
|
1350
|
-
|
|
1503
|
+
const inCadence = cadence === void 0 ? sorted : sorted.filter((a) => retentionClassOf(a) === cadence);
|
|
1504
|
+
if (inCadence.length <= retentionCount) return {
|
|
1351
1505
|
keep: sorted,
|
|
1352
1506
|
drop: []
|
|
1353
1507
|
};
|
|
1508
|
+
const drop = inCadence.slice(retentionCount);
|
|
1509
|
+
const dropped = new Set(drop);
|
|
1354
1510
|
return {
|
|
1355
|
-
keep: sorted.
|
|
1356
|
-
drop
|
|
1511
|
+
keep: sorted.filter((a) => !dropped.has(a)),
|
|
1512
|
+
drop
|
|
1357
1513
|
};
|
|
1358
1514
|
}
|
|
1359
1515
|
/**
|
|
@@ -1637,7 +1793,8 @@ function requestSignature(request) {
|
|
|
1637
1793
|
destinations: [...request.destinations ?? []].toSorted(),
|
|
1638
1794
|
locations: [...request.locations ?? []].toSorted(),
|
|
1639
1795
|
label: request.label ?? null,
|
|
1640
|
-
retentionCount: request.retentionCount ?? null
|
|
1796
|
+
retentionCount: request.retentionCount ?? null,
|
|
1797
|
+
databases: [...request.databases ?? []].toSorted()
|
|
1641
1798
|
});
|
|
1642
1799
|
}
|
|
1643
1800
|
//#endregion
|
|
@@ -1696,6 +1853,10 @@ var BACKUP_SCHEDULES_COLUMNS = [
|
|
|
1696
1853
|
name: "data_sources",
|
|
1697
1854
|
type: "JSON"
|
|
1698
1855
|
},
|
|
1856
|
+
{
|
|
1857
|
+
name: "databases",
|
|
1858
|
+
type: "JSON"
|
|
1859
|
+
},
|
|
1699
1860
|
{
|
|
1700
1861
|
name: "last_run_at",
|
|
1701
1862
|
type: "INTEGER"
|
|
@@ -1785,6 +1946,7 @@ function mapScheduleToRow(s) {
|
|
|
1785
1946
|
location_ids: [...s.locationIds],
|
|
1786
1947
|
retention_count: s.retentionCount,
|
|
1787
1948
|
data_sources: s.dataSources ? [...s.dataSources] : null,
|
|
1949
|
+
databases: s.databases ? [...s.databases] : null,
|
|
1788
1950
|
last_run_at: s.lastAttemptAt ?? null,
|
|
1789
1951
|
last_success_at: s.lastSuccessAt ?? null,
|
|
1790
1952
|
last_error: s.lastError ?? null
|
|
@@ -1801,6 +1963,12 @@ function parseStringArray(raw) {
|
|
|
1801
1963
|
if (!Array.isArray(value)) return [];
|
|
1802
1964
|
return value.filter((v) => typeof v === "string");
|
|
1803
1965
|
}
|
|
1966
|
+
/** Known database ids only: an unknown name in a stored row is dropped, not carried. */
|
|
1967
|
+
function parseDatabaseIds(raw) {
|
|
1968
|
+
const out = [];
|
|
1969
|
+
for (const id of parseStringArray(raw)) if (id === "settings" || id === "events" || id === "history") out.push(id);
|
|
1970
|
+
return out;
|
|
1971
|
+
}
|
|
1804
1972
|
function tryParseJson(raw) {
|
|
1805
1973
|
if (raw.length === 0) return null;
|
|
1806
1974
|
try {
|
|
@@ -1814,6 +1982,8 @@ function mapRowToSchedule(row) {
|
|
|
1814
1982
|
if (!id) return null;
|
|
1815
1983
|
const dataSourcesRaw = row["data_sources"];
|
|
1816
1984
|
const dataSources = dataSourcesRaw === null || dataSourcesRaw === void 0 ? void 0 : parseStringArray(dataSourcesRaw);
|
|
1985
|
+
const databasesRaw = row["databases"];
|
|
1986
|
+
const databases = databasesRaw === null || databasesRaw === void 0 ? void 0 : parseDatabaseIds(databasesRaw);
|
|
1817
1987
|
const lastRunRaw = row["last_run_at"];
|
|
1818
1988
|
const lastAttemptAt = typeof lastRunRaw === "number" && lastRunRaw > 0 ? lastRunRaw : void 0;
|
|
1819
1989
|
const lastSuccessRaw = row["last_success_at"];
|
|
@@ -1828,6 +1998,7 @@ function mapRowToSchedule(row) {
|
|
|
1828
1998
|
locationIds: parseStringArray(row["location_ids"]),
|
|
1829
1999
|
retentionCount: Number(row["retention_count"] ?? 7),
|
|
1830
2000
|
...dataSources !== void 0 ? { dataSources } : {},
|
|
2001
|
+
...databases !== void 0 && databases.length > 0 ? { databases } : {},
|
|
1831
2002
|
...lastAttemptAt !== void 0 ? { lastAttemptAt } : {},
|
|
1832
2003
|
...lastSuccessAt !== void 0 ? { lastSuccessAt } : {},
|
|
1833
2004
|
...lastError !== void 0 ? { lastError } : {}
|
|
@@ -2080,6 +2251,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2080
2251
|
this.ctx.logger.error("backup-orchestrator: schedule table init failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
2081
2252
|
this.schedules = null;
|
|
2082
2253
|
}
|
|
2254
|
+
await this.seedWeekly();
|
|
2083
2255
|
const settingsStore = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
|
|
2084
2256
|
this.encryptionKeys = settingsStore ? new BackupEncryptionKeyStore(settingsStore) : null;
|
|
2085
2257
|
const provider = {
|
|
@@ -2100,6 +2272,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2100
2272
|
upsertDestinationPolicy: (input) => this.upsertDestinationPolicy(input),
|
|
2101
2273
|
previewSchedule: (input) => this.previewSchedule(input),
|
|
2102
2274
|
listSchedules: () => this.listSchedules(),
|
|
2275
|
+
listAvailableDatabases: () => this.listAvailableDatabases(),
|
|
2103
2276
|
upsertSchedule: (input) => this.upsertSchedule(input),
|
|
2104
2277
|
deleteSchedule: (input) => this.deleteSchedule(input)
|
|
2105
2278
|
};
|
|
@@ -2385,7 +2558,8 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2385
2558
|
...input?.destinations ? { destinations: input.destinations } : {},
|
|
2386
2559
|
...input?.locations ? { locations: input.locations } : {},
|
|
2387
2560
|
...input?.label !== void 0 ? { label: input.label } : {},
|
|
2388
|
-
...input?.retentionCount !== void 0 ? { retentionCount: input.retentionCount } : {}
|
|
2561
|
+
...input?.retentionCount !== void 0 ? { retentionCount: input.retentionCount } : {},
|
|
2562
|
+
...input?.databases ? { databases: input.databases } : {}
|
|
2389
2563
|
};
|
|
2390
2564
|
const submitted = this.runQueue.submit(request);
|
|
2391
2565
|
if (submitted.queued) this.ctx.logger.info(submitted.joined ? "backup trigger: identical run already queued — joined it" : "backup trigger: a run is in flight — enqueued behind it", { meta: { runId: submitted.runId } });
|
|
@@ -2459,6 +2633,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2459
2633
|
signal,
|
|
2460
2634
|
onArchiveBytes: (bytes) => progress.setStagedBytes(bytes),
|
|
2461
2635
|
owner: this.databaseOwner(),
|
|
2636
|
+
...input.databases ? { databases: input.databases } : {},
|
|
2462
2637
|
...encryptTo !== null ? { encryptTo: encryptTo.publicKey } : {}
|
|
2463
2638
|
});
|
|
2464
2639
|
} catch (err) {
|
|
@@ -2491,6 +2666,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2491
2666
|
sizeBytes: result.sizeBytes,
|
|
2492
2667
|
archiveManifest: result.manifest,
|
|
2493
2668
|
retentionCount: input.retentionCount ?? policy.retentionCount,
|
|
2669
|
+
databases: input.databases ?? require_restore_archive.DEFAULT_BACKUP_DATABASES,
|
|
2494
2670
|
createdAt,
|
|
2495
2671
|
label: formatArchiveLabel(dest.id, createdAt, input.label),
|
|
2496
2672
|
...result.encryption !== void 0 ? { encryption: result.encryption } : {},
|
|
@@ -2562,9 +2738,9 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2562
2738
|
};
|
|
2563
2739
|
return {
|
|
2564
2740
|
listDatabases: async () => {
|
|
2565
|
-
return (await this.ctx.api.databaseSnapshot.listDatabases.query({}, pin())).databases
|
|
2741
|
+
return (await this.ctx.api.databaseSnapshot.listDatabases.query({}, pin())).databases;
|
|
2566
2742
|
},
|
|
2567
|
-
writeSnapshot: async () => this.ctx.api.databaseSnapshot.writeSnapshot.mutate({}, pin())
|
|
2743
|
+
writeSnapshot: async (databaseId) => this.ctx.api.databaseSnapshot.writeSnapshot.mutate({ databaseId }, pin())
|
|
2568
2744
|
};
|
|
2569
2745
|
}
|
|
2570
2746
|
/**
|
|
@@ -2616,10 +2792,11 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2616
2792
|
sizeBytes: input.sizeBytes,
|
|
2617
2793
|
label: input.label,
|
|
2618
2794
|
manifest: input.archiveManifest,
|
|
2619
|
-
...input.encryption !== void 0 ? { encryption: input.encryption } : {}
|
|
2795
|
+
...input.encryption !== void 0 ? { encryption: input.encryption } : {},
|
|
2796
|
+
databases: input.databases
|
|
2620
2797
|
});
|
|
2621
2798
|
await this.manifestLock.run(input.locationId, async () => {
|
|
2622
|
-
const { keep, drop } = applyRetention([...(await readLocationManifest(this.storageApi(), input.locationId)).archives, entry], input.retentionCount);
|
|
2799
|
+
const { keep, drop } = applyRetention([...(await readLocationManifest(this.storageApi(), input.locationId)).archives, entry], input.retentionCount, retentionClassOf(entry));
|
|
2623
2800
|
for (const stale of drop) try {
|
|
2624
2801
|
await this.ctx.api.storage.delete.mutate({
|
|
2625
2802
|
location: input.locationId,
|
|
@@ -2673,7 +2850,8 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
2673
2850
|
sizeBytes: a.sizeBytes,
|
|
2674
2851
|
...a.label !== void 0 ? { label: a.label } : {},
|
|
2675
2852
|
locations: [...a.manifest.locations],
|
|
2676
|
-
...a.encryption !== void 0 ? { encryption: a.encryption } : {}
|
|
2853
|
+
...a.encryption !== void 0 ? { encryption: a.encryption } : {},
|
|
2854
|
+
...a.databases !== void 0 ? { databases: [...a.databases] } : {}
|
|
2677
2855
|
}));
|
|
2678
2856
|
}
|
|
2679
2857
|
/**
|
|
@@ -3040,6 +3218,55 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3040
3218
|
}
|
|
3041
3219
|
}
|
|
3042
3220
|
/**
|
|
3221
|
+
* A schedule that asks for events/history while the owner has neither open
|
|
3222
|
+
* would only repeat the nightly archive (D852: the weekly schedule has
|
|
3223
|
+
* nothing to carry until those files exist). Said on the record, no archive
|
|
3224
|
+
* built, no outcome stamped. An owner that cannot answer never skips: the
|
|
3225
|
+
* run goes ahead and fails — or succeeds — in the open.
|
|
3226
|
+
*/
|
|
3227
|
+
async nothingToCarry(schedule) {
|
|
3228
|
+
const requested = databasesOfSchedule(schedule);
|
|
3229
|
+
if (!requested.some((id) => id !== "settings")) return false;
|
|
3230
|
+
let owned;
|
|
3231
|
+
try {
|
|
3232
|
+
owned = (await this.databaseOwner().listDatabases()).map((d) => d.databaseId);
|
|
3233
|
+
} catch (err) {
|
|
3234
|
+
this.ctx.logger.warn("Scheduled backup: the database owner did not answer — running anyway", { meta: {
|
|
3235
|
+
scheduleId: schedule.id,
|
|
3236
|
+
label: schedule.label,
|
|
3237
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3238
|
+
} });
|
|
3239
|
+
return false;
|
|
3240
|
+
}
|
|
3241
|
+
if (!hasNothingBeyondSettings(requested, owned)) return false;
|
|
3242
|
+
this.ctx.logger.info("Scheduled backup skipped — no database it carries exists yet", { meta: {
|
|
3243
|
+
scheduleId: schedule.id,
|
|
3244
|
+
label: schedule.label,
|
|
3245
|
+
requested: [...requested],
|
|
3246
|
+
owned
|
|
3247
|
+
} });
|
|
3248
|
+
return true;
|
|
3249
|
+
}
|
|
3250
|
+
/**
|
|
3251
|
+
* Seed the weekly "events & history" schedule (D852) — once, and never over
|
|
3252
|
+
* anything the operator has: see `planWeeklySeed`.
|
|
3253
|
+
*/
|
|
3254
|
+
async seedWeekly() {
|
|
3255
|
+
if (!this.schedules) return;
|
|
3256
|
+
try {
|
|
3257
|
+
const store = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
|
|
3258
|
+
if (!store) return;
|
|
3259
|
+
const seed = await seedWeeklySchedule(this.schedules, new BackupSeedMarkerStore(store));
|
|
3260
|
+
if (seed === null) return;
|
|
3261
|
+
this.ctx.logger.info("backup: seeded the weekly events & history schedule", { meta: {
|
|
3262
|
+
scheduleId: seed.id,
|
|
3263
|
+
destinationIds: [...seed.locationIds]
|
|
3264
|
+
} });
|
|
3265
|
+
} catch (err) {
|
|
3266
|
+
this.ctx.logger.warn("backup: the weekly schedule could not be seeded", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
/**
|
|
3043
3270
|
* Fire one schedule and RECORD what happened to it, naming every
|
|
3044
3271
|
* destination. Three outcomes, three different persisted states —
|
|
3045
3272
|
* because "fired" and "backed up" were the same field until D384:
|
|
@@ -3050,13 +3277,15 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3050
3277
|
*/
|
|
3051
3278
|
async runScheduledBackup(schedule, firedAt) {
|
|
3052
3279
|
const destinationIds = [...schedule.locationIds];
|
|
3280
|
+
if (await this.nothingToCarry(schedule)) return;
|
|
3053
3281
|
let failure;
|
|
3054
3282
|
try {
|
|
3055
3283
|
const result = await this.triggerBackup({
|
|
3056
3284
|
destinations: destinationIds,
|
|
3057
3285
|
...schedule.dataSources && schedule.dataSources.length > 0 ? { locations: [...schedule.dataSources] } : {},
|
|
3058
3286
|
label: schedule.label,
|
|
3059
|
-
retentionCount: schedule.retentionCount
|
|
3287
|
+
retentionCount: schedule.retentionCount,
|
|
3288
|
+
...schedule.databases ? { databases: [...schedule.databases] } : {}
|
|
3060
3289
|
});
|
|
3061
3290
|
if (result.entries.length === 0 && !result.cancelled) failure = `no destination accepted the archive (${destinationIds.join(", ")})`;
|
|
3062
3291
|
} catch (err) {
|
|
@@ -3089,6 +3318,25 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3089
3318
|
} });
|
|
3090
3319
|
}
|
|
3091
3320
|
}
|
|
3321
|
+
/**
|
|
3322
|
+
* The database files the owner has open right now, for the selection UI. An
|
|
3323
|
+
* owner that cannot answer is `answered: false` — never an empty list, which
|
|
3324
|
+
* the UI would read as "none exists yet".
|
|
3325
|
+
*/
|
|
3326
|
+
async listAvailableDatabases() {
|
|
3327
|
+
try {
|
|
3328
|
+
return {
|
|
3329
|
+
answered: true,
|
|
3330
|
+
databases: (await this.databaseOwner().listDatabases()).map((d) => d.databaseId)
|
|
3331
|
+
};
|
|
3332
|
+
} catch (err) {
|
|
3333
|
+
this.ctx.logger.warn("Backup database list: the database owner did not answer", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
3334
|
+
return {
|
|
3335
|
+
answered: false,
|
|
3336
|
+
databases: []
|
|
3337
|
+
};
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3092
3340
|
async listSchedules() {
|
|
3093
3341
|
if (!this.schedules) return [];
|
|
3094
3342
|
return (await this.schedules.list()).map((s) => {
|
|
@@ -3105,6 +3353,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3105
3353
|
locationIds: [...s.locationIds],
|
|
3106
3354
|
retentionCount: s.retentionCount,
|
|
3107
3355
|
...s.dataSources !== void 0 ? { dataSources: [...s.dataSources] } : {},
|
|
3356
|
+
...s.databases !== void 0 ? { databases: [...s.databases] } : {},
|
|
3108
3357
|
...s.lastAttemptAt !== void 0 ? { lastAttemptAt: s.lastAttemptAt } : {},
|
|
3109
3358
|
...s.lastSuccessAt !== void 0 ? { lastSuccessAt: s.lastSuccessAt } : {},
|
|
3110
3359
|
...s.lastError !== void 0 ? { lastError: s.lastError } : {},
|
|
@@ -3126,6 +3375,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3126
3375
|
locationIds: [...input.locationIds],
|
|
3127
3376
|
retentionCount: input.retentionCount,
|
|
3128
3377
|
...input.dataSources && input.dataSources.length > 0 ? { dataSources: [...input.dataSources] } : {},
|
|
3378
|
+
...input.databases && input.databases.length > 0 ? { databases: [...input.databases] } : {},
|
|
3129
3379
|
...existing?.lastAttemptAt !== void 0 ? { lastAttemptAt: existing.lastAttemptAt } : {},
|
|
3130
3380
|
...existing?.lastSuccessAt !== void 0 ? { lastSuccessAt: existing.lastSuccessAt } : {},
|
|
3131
3381
|
...existing?.lastError !== void 0 ? { lastError: existing.lastError } : {}
|
|
@@ -3144,6 +3394,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3144
3394
|
locationIds: [...next.locationIds],
|
|
3145
3395
|
retentionCount: next.retentionCount,
|
|
3146
3396
|
...next.dataSources !== void 0 ? { dataSources: [...next.dataSources] } : {},
|
|
3397
|
+
...next.databases !== void 0 ? { databases: [...next.databases] } : {},
|
|
3147
3398
|
...next.lastAttemptAt !== void 0 ? { lastAttemptAt: next.lastAttemptAt } : {},
|
|
3148
3399
|
...next.lastSuccessAt !== void 0 ? { lastSuccessAt: next.lastSuccessAt } : {},
|
|
3149
3400
|
...next.lastError !== void 0 ? { lastError: next.lastError } : {},
|