ca003c88ba
On S3, index files and the tree segments read back when a snapshot is written are fetched 16 at a time through the storage's S3 client (IBackend::getRanges(), getMany()). Blobs that follow each other in a pack are read as one range on every location. The snapshot is written in a step of its own and the run shows "commit" meanwhile. On a 1 TB production repository the check went from about 4 hours to 3.5 minutes. backup:status and the web interface list the runs of the last 7 days, running ones and at least the newest 5; --all / "Show older runs" list all. Durations of a day or more show the days.
41 lines
2.2 KiB
JavaScript
41 lines
2.2 KiB
JavaScript
// SPDX-FileCopyrightText: 2026 Dillard Blom
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
import axios from '@nextcloud/axios'
|
|
import { generateUrl } from '@nextcloud/router'
|
|
|
|
const url = (path) => generateUrl('/apps/ng_backup/api' + path)
|
|
|
|
/** Unwraps {error} responses into thrown Errors with the server's message. */
|
|
async function call(method, path, data) {
|
|
try {
|
|
const response = await axios({ method, url: url(path), data, params: method === 'get' ? data : undefined })
|
|
return response.data
|
|
} catch (e) {
|
|
throw new Error(e.response?.data?.error || e.message)
|
|
}
|
|
}
|
|
|
|
export default {
|
|
status: (allRuns = false) => call('get', '/status', allRuns ? { allRuns: true } : undefined),
|
|
initKey: (passphrase, deleteDelayDays, label) => call('post', '/key', { passphrase, deleteDelayDays, label }),
|
|
addSlot: (passphrase, label) => call('post', '/key/slots', { passphrase, label }),
|
|
replaceSlot: (slot, passphrase, label) => call('put', `/key/slots/${slot}`, { passphrase, label }),
|
|
removeSlot: (slot) => call('delete', `/key/slots/${slot}`),
|
|
trash: (targetId) => call('get', `/targets/${targetId}/trash`),
|
|
untrash: (targetId, snapshotId) => call('post', `/targets/${targetId}/trash/${snapshotId}`),
|
|
kitUrl: () => url('/key/kit'),
|
|
confirmKit: (accepted, phrase, code) => call('post', '/key/confirm', { accepted, phrase, code }),
|
|
backends: () => call('get', '/backends'),
|
|
addTarget: (target) => call('post', '/targets', target),
|
|
targetSettings: (id) => call('get', `/targets/${id}/settings`),
|
|
updateTarget: (id, target) => call('put', `/targets/${id}`, target),
|
|
removeTarget: (id) => call('delete', `/targets/${id}`),
|
|
testTarget: (id) => call('post', `/targets/${id}/test`),
|
|
setTargetLimit: (id, maxGb) => call('put', `/targets/${id}/limit`, { maxGb }),
|
|
startBackup: (targetId, label) => call('post', '/backups', { targetId, label }),
|
|
setSchedule: (time) => call('put', '/schedule', { time }),
|
|
snapshots: (targetId) => call('get', `/targets/${targetId}/snapshots`),
|
|
browse: (targetId, snapshotId, path) => call('get', `/targets/${targetId}/snapshots/${snapshotId}/browse`, { path }),
|
|
startRestore: (targetId, snapshotId, path, mode) => call('post', '/restores', { targetId, snapshotId, path, mode }),
|
|
}
|