u
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* @file backupAutomat.js
|
||||
* @description Manages backup status and backup archives (`GET /backup`, `POST /backup/run`).
|
||||
* @description Manages backup status, archive listings, and VFS file recovery from backup archives (`GET /backup`, `GET /backup/:id/vfs`, `POST /backup/:id/vfs/recover`).
|
||||
*
|
||||
* Upstream Triggers:
|
||||
* - `authAutomat`: Subscribes to auth state changes — calls `actions.load()` on
|
||||
* `'authed'` with a `selectedCompanyId`, and `actions.clear()` on `'anon'`.
|
||||
* - `sseAutomat`: Subscribes to `'backup'` event (if dispatched) to reload silently.
|
||||
* - UI / Settings: Calls to `actions.load()`, `actions.reload()`, or `actions.runBackup()`.
|
||||
* - UI / Settings: Calls to `actions.load()`, `actions.reload()`, `actions.listBackupVfs()`, or `actions.recoverBackupVfs()`.
|
||||
*/
|
||||
|
||||
import { Automat } from 'react-automat';
|
||||
@@ -41,17 +41,16 @@ import sseAutomat from './sseAutomat';
|
||||
* @typedef {Object} BackupState
|
||||
* @property {'idle'|'loading'|'ready'|'failed'} status Load lifecycle state
|
||||
* @property {string|null} error Last error message
|
||||
* @property {boolean} runningBackup Whether a manual backup run is currently in progress
|
||||
* @property {BackupStatus|null} backupStatus Service status and retention settings
|
||||
* @property {{ counts: { hourly: number, daily: number, monthly: number }, hourly: BackupItem[], daily: BackupItem[], monthly: BackupItem[] }} backups Grouped backup archives
|
||||
* @property {object|null} lastRunResult Manifest/result from the most recent manual backup run
|
||||
* @property {Record<string, Array<{ name: string, size: number, mime: string, mtime: string }>>} vfsFilesByBackup
|
||||
* @property {Record<string, boolean>} vfsLoadingByBackup
|
||||
*/
|
||||
|
||||
/** @type {BackupState} */
|
||||
const initialState = {
|
||||
status: 'idle',
|
||||
error: null,
|
||||
runningBackup: false,
|
||||
backupStatus: null,
|
||||
backups: {
|
||||
counts: { hourly: 0, daily: 0, monthly: 0 },
|
||||
@@ -59,7 +58,8 @@ const initialState = {
|
||||
daily: [],
|
||||
monthly: [],
|
||||
},
|
||||
lastRunResult: null,
|
||||
vfsFilesByBackup: {},
|
||||
vfsLoadingByBackup: {},
|
||||
};
|
||||
|
||||
let backupAutomat;
|
||||
@@ -141,30 +141,50 @@ const actions = {
|
||||
},
|
||||
// #endregion
|
||||
|
||||
// #region runBackup
|
||||
// MARK: calls POST /api/backup/run from ./api/index.js
|
||||
// #region listBackupVfs
|
||||
// MARK: calls GET /api/backup/:id/vfs from ./api/index.js
|
||||
/**
|
||||
* Triggers an immediate manual backup run on the backend.
|
||||
* Retrieves the list of VFS files stored inside a specific backup.
|
||||
*
|
||||
* @returns {Promise<object>} The backup run result containing manifest and pruneResult
|
||||
* @param {string} backupId Identifier of the backup
|
||||
* @param {number} [companyId] Optional company ID override
|
||||
* @returns {Promise<Array<{ name: string, size: number, mime: string, mtime: string }>>}
|
||||
*/
|
||||
async runBackup() {
|
||||
backupAutomat.setState({ runningBackup: true, error: null });
|
||||
async listBackupVfs(backupId, companyId) {
|
||||
if (!backupId) return [];
|
||||
backupAutomat.setState({
|
||||
vfsLoadingByBackup: { ...backupAutomat.state.vfsLoadingByBackup, [backupId]: true },
|
||||
});
|
||||
try {
|
||||
const result = await backupApi.run();
|
||||
backupAutomat.setState({ lastRunResult: result });
|
||||
await actions.reload();
|
||||
return result;
|
||||
} catch (err) {
|
||||
const error = err?.message ?? String(err);
|
||||
backupAutomat.setState({ error });
|
||||
throw err;
|
||||
const res = await backupApi.listVfs(backupId, companyId);
|
||||
const files = Array.isArray(res?.files) ? res.files : [];
|
||||
backupAutomat.setState({
|
||||
vfsFilesByBackup: { ...backupAutomat.state.vfsFilesByBackup, [backupId]: files },
|
||||
});
|
||||
return files;
|
||||
} finally {
|
||||
backupAutomat.setState({ runningBackup: false });
|
||||
backupAutomat.setState({
|
||||
vfsLoadingByBackup: { ...backupAutomat.state.vfsLoadingByBackup, [backupId]: false },
|
||||
});
|
||||
}
|
||||
},
|
||||
// #endregion
|
||||
|
||||
// #region recoverBackupVfs
|
||||
// MARK: calls POST /api/backup/:id/vfs/recover from ./api/index.js
|
||||
/**
|
||||
* Restores a single VFS file from the specified backup into the active VFS.
|
||||
*
|
||||
* @param {string} backupId Identifier of the backup
|
||||
* @param {string} path Relative file path within the VFS
|
||||
* @param {number} [companyId] Optional company ID override
|
||||
* @returns {Promise<object>} Recovery result
|
||||
*/
|
||||
async recoverBackupVfs(backupId, path, companyId) {
|
||||
return backupApi.recoverVfs(backupId, path, companyId);
|
||||
},
|
||||
// #endregion
|
||||
|
||||
/**
|
||||
* Resets the automat state to initial empty values.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user