diff --git a/CHANGELOG.md b/CHANGELOG.md index a02f0b8bc..089fb50ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - [Backup NG Overview] List the Backup NG job's modes [#3169](https://github.com/vatesfr/xen-orchestra/issues/3169) (PR [#3277](https://github.com/vatesfr/xen-orchestra/pull/3277)) - [Backup NG form] Move "Use compression" checkbox in the advanced settings [#2711](https://github.com/vatesfr/xen-orchestra/issues/2711) (PR [#3281](https://github.com/vatesfr/xen-orchestra/pull/3281)) - [Backup NG form] Ability to remove previous backups first before backup the VMs [#3212](https://github.com/vatesfr/xen-orchestra/issues/3212) (PR [#3260](https://github.com/vatesfr/xen-orchestra/pull/3260)) +- [Backup reports] Send report for the interrupted backup jobs on the server startup [#2998](https://github.com/vatesfr/xen-orchestra/issues/#2998) (PR [3164](https://github.com/vatesfr/xen-orchestra/pull/3164) [3154](https://github.com/vatesfr/xen-orchestra/pull/3154)) ### Bug fixes @@ -49,7 +50,7 @@ - xo-remote-parser v0.5.0 - complex-matcher v0.4.0 -- xo-server-backup-reports v0.12.3 +- xo-server-backup-reports v0.13.0 - xo-server v5.23.0 - xo-web v5.23.0 diff --git a/packages/xo-server-backup-reports/src/index.js b/packages/xo-server-backup-reports/src/index.js index c1c443523..1f10f939a 100644 --- a/packages/xo-server-backup-reports/src/index.js +++ b/packages/xo-server-backup-reports/src/index.js @@ -132,7 +132,7 @@ class BackupReportsXoPlugin { ).catch(logError) } - async _backupNgListener (_1, _2, { timezone }, runJobId) { + async _backupNgListener (_1, _2, schedule, runJobId) { const xo = this._xo const log = await xo.getBackupNgLogs(runJobId) @@ -144,8 +144,12 @@ class BackupReportsXoPlugin { return } + if (schedule === undefined) { + schedule = await xo.getSchedule(log.scheduleId) + } + const jobName = (await xo.getJob(log.jobId, 'backup')).name - const formatDate = createDateFormater(timezone) + const formatDate = createDateFormater(schedule.timezone) const getTemporalDataMarkdown = createGetTemporalDataMarkdown(formatDate) if ( diff --git a/packages/xo-server/src/index.js b/packages/xo-server/src/index.js index 52e8df917..8e54c4b25 100644 --- a/packages/xo-server/src/index.js +++ b/packages/xo-server/src/index.js @@ -637,6 +637,7 @@ export default async function main (args) { if (!includes(args, '--safe-mode')) { await registerPlugins(xo) + xo.emit('plugins:registered') } // Gracefully shutdown on signals. diff --git a/packages/xo-server/src/xo-mixins/jobs/index.js b/packages/xo-server/src/xo-mixins/jobs/index.js index 8a35ea778..2fb56448f 100644 --- a/packages/xo-server/src/xo-mixins/jobs/index.js +++ b/packages/xo-server/src/xo-mixins/jobs/index.js @@ -2,13 +2,13 @@ import type { Pattern } from 'value-matcher' -import { CancelToken } from 'promise-toolbox' +import { CancelToken, ignoreErrors } from 'promise-toolbox' import { map as mapToArray } from 'lodash' import { noSuchObject } from 'xo-common/api-errors' import Collection from '../../collection/redis' import patch from '../../patch' -import { serializeError } from '../../utils' +import { asyncMap, serializeError } from '../../utils' import type Logger from '../logs/loggers/abstract' import { type Schedule } from '../scheduling' @@ -154,6 +154,26 @@ export default class Jobs { xo.getLogger('jobs').then(logger => { this._logger = logger }) + + // it sends a report for the interrupted backup jobs + this._app.on('plugins:registered', () => + asyncMap(this._jobs.get(), job => { + // only the interrupted backup jobs have the runId property + if (job.runId === undefined) { + return + } + + this._app.emit( + 'job:terminated', + undefined, + job, + undefined, + // This cast can be removed after merging the PR: https://github.com/vatesfr/xen-orchestra/pull/3209 + String(job.runId) + ) + return this.updateJob({ id: job.id, runId: null }) + }) + ) }) } @@ -258,6 +278,8 @@ export default class Jobs { type, }) + // runId is a temporary property used to check if the report is sent after the server interruption + this.updateJob({ id, runId: runJobId })::ignoreErrors() runningJobs[id] = runJobId const runs = this._runs @@ -295,6 +317,7 @@ export default class Jobs { }) throw error } finally { + ;this.updateJob({ id, runId: null })::ignoreErrors() delete runningJobs[id] delete runs[runJobId] if (session !== undefined) {