mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
210 lines
6.4 KiB
Vue
210 lines
6.4 KiB
Vue
<!--
|
||
- SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
|
||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||
-->
|
||
|
||
<template>
|
||
<NcSettingsSection
|
||
:name="t('settings', 'Background jobs')"
|
||
:description="t('settings', 'For the server to work properly, it\'s important to configure background jobs correctly. Cron is the recommended setting. Please see the documentation for more information.')"
|
||
:doc-url="backgroundJobsDocUrl">
|
||
<template v-if="lastCron !== 0">
|
||
<NcNoteCard v-if="oldExecution" type="error">
|
||
{{ t('settings', 'Last job execution ran {time}. Something seems wrong.', { time: relativeTime }) }}
|
||
</NcNoteCard>
|
||
|
||
<NcNoteCard v-else-if="longExecutionCron" type="warning">
|
||
{{ t('settings', "Some jobs have not been executed since {maxAgeRelativeTime}. Please consider increasing the execution frequency.", { maxAgeRelativeTime }) }}
|
||
</NcNoteCard>
|
||
|
||
<NcNoteCard v-else-if="longExecutionNotCron" type="warning">
|
||
{{ t('settings', "Some jobs have not been executed since {maxAgeRelativeTime}. Please consider switching to system cron.", { maxAgeRelativeTime }) }}
|
||
</NcNoteCard>
|
||
|
||
<NcNoteCard v-else type="success">
|
||
{{ t('settings', 'Last job ran {relativeTime}.', { relativeTime }) }}
|
||
</NcNoteCard>
|
||
</template>
|
||
|
||
<NcNoteCard v-else type="error">
|
||
{{ t('settings', 'Background job did not run yet!') }}
|
||
</NcNoteCard>
|
||
|
||
<NcCheckboxRadioSwitch
|
||
type="radio"
|
||
:checked.sync="backgroundJobsMode"
|
||
name="backgroundJobsMode"
|
||
value="ajax"
|
||
class="ajaxSwitch"
|
||
@update:checked="onBackgroundJobModeChanged">
|
||
{{ t('settings', 'AJAX') }}
|
||
</NcCheckboxRadioSwitch>
|
||
<em>{{ t('settings', 'Execute one task with each page loaded. Use case: Single account instance.') }}</em>
|
||
|
||
<NcCheckboxRadioSwitch
|
||
type="radio"
|
||
:checked.sync="backgroundJobsMode"
|
||
name="backgroundJobsMode"
|
||
value="webcron"
|
||
@update:checked="onBackgroundJobModeChanged">
|
||
{{ t('settings', 'Webcron') }}
|
||
</NcCheckboxRadioSwitch>
|
||
<em>{{ t('settings', 'cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (1–5 accounts depending on the usage).') }}</em>
|
||
|
||
<NcCheckboxRadioSwitch
|
||
type="radio"
|
||
:disabled="!cliBasedCronPossible"
|
||
:checked.sync="backgroundJobsMode"
|
||
value="cron"
|
||
name="backgroundJobsMode"
|
||
@update:checked="onBackgroundJobModeChanged">
|
||
{{ t('settings', 'Cron (Recommended)') }}
|
||
</NcCheckboxRadioSwitch>
|
||
<!-- eslint-disable-next-line vue/no-v-html The translation is sanitized-->
|
||
<em v-html="cronLabel" />
|
||
</NcSettingsSection>
|
||
</template>
|
||
|
||
<script>
|
||
import axios from '@nextcloud/axios'
|
||
import { showError } from '@nextcloud/dialogs'
|
||
import { loadState } from '@nextcloud/initial-state'
|
||
import moment from '@nextcloud/moment'
|
||
import { confirmPassword } from '@nextcloud/password-confirmation'
|
||
import { generateOcsUrl } from '@nextcloud/router'
|
||
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
|
||
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
|
||
import NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection'
|
||
import logger from '../../logger.ts'
|
||
|
||
const lastCron = loadState('settings', 'lastCron')
|
||
const cronMaxAge = loadState('settings', 'cronMaxAge', '')
|
||
const backgroundJobsMode = loadState('settings', 'backgroundJobsMode', 'cron')
|
||
const cliBasedCronPossible = loadState('settings', 'cliBasedCronPossible', true)
|
||
const cliBasedCronUser = loadState('settings', 'cliBasedCronUser', 'www-data')
|
||
const backgroundJobsDocUrl = loadState('settings', 'backgroundJobsDocUrl')
|
||
|
||
export default {
|
||
name: 'BackgroundJob',
|
||
|
||
components: {
|
||
NcCheckboxRadioSwitch,
|
||
NcSettingsSection,
|
||
NcNoteCard,
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
lastCron,
|
||
cronMaxAge,
|
||
backgroundJobsMode,
|
||
cliBasedCronPossible,
|
||
cliBasedCronUser,
|
||
backgroundJobsDocUrl,
|
||
relativeTime: moment(lastCron * 1000).fromNow(),
|
||
maxAgeRelativeTime: moment(cronMaxAge * 1000).fromNow(),
|
||
}
|
||
},
|
||
|
||
computed: {
|
||
cronLabel() {
|
||
let desc = t('settings', 'Use system cron service to call the cron.php file every 5 minutes.')
|
||
if (this.cliBasedCronPossible) {
|
||
desc += '<br>' + t('settings', 'The cron.php needs to be executed by the system account "{user}".', { user: this.cliBasedCronUser })
|
||
} else {
|
||
desc += '<br>' + t('settings', 'The PHP POSIX extension is required. See {linkstart}PHP documentation{linkend} for more details.', {
|
||
linkstart: '<a target="_blank" rel="noreferrer nofollow" class="external" href="https://www.php.net/manual/en/book.posix.php">',
|
||
linkend: '</a>',
|
||
}, undefined, { escape: false })
|
||
}
|
||
return desc
|
||
},
|
||
|
||
oldExecution() {
|
||
return Date.now() / 1000 - this.lastCron > 600
|
||
},
|
||
|
||
longExecutionNotCron() {
|
||
return Date.now() / 1000 - this.cronMaxAge > 12 * 3600 && this.backgroundJobsMode !== 'cron'
|
||
},
|
||
|
||
longExecutionCron() {
|
||
return Date.now() / 1000 - this.cronMaxAge > 24 * 3600 && this.backgroundJobsMode === 'cron'
|
||
},
|
||
},
|
||
|
||
methods: {
|
||
async onBackgroundJobModeChanged(backgroundJobsMode) {
|
||
const url = generateOcsUrl('/apps/provisioning_api/api/v1/config/apps/{appId}/{key}', {
|
||
appId: 'core',
|
||
key: 'backgroundjobs_mode',
|
||
})
|
||
|
||
await confirmPassword()
|
||
|
||
try {
|
||
const { data } = await axios.post(url, {
|
||
value: backgroundJobsMode,
|
||
})
|
||
this.handleResponse({
|
||
status: data.ocs?.meta?.status,
|
||
})
|
||
} catch (e) {
|
||
this.handleResponse({
|
||
errorMessage: t('settings', 'Unable to update background job mode'),
|
||
error: e,
|
||
})
|
||
}
|
||
},
|
||
|
||
async handleResponse({ status, errorMessage, error }) {
|
||
if (status === 'ok') {
|
||
await this.deleteError()
|
||
} else {
|
||
showError(errorMessage)
|
||
logger.error(errorMessage, error)
|
||
}
|
||
},
|
||
|
||
async deleteError() {
|
||
// clear cron errors on background job mode change
|
||
const url = generateOcsUrl('/apps/provisioning_api/api/v1/config/apps/{appId}/{key}', {
|
||
appId: 'core',
|
||
key: 'cronErrors',
|
||
})
|
||
|
||
await confirmPassword()
|
||
|
||
try {
|
||
await axios.delete(url)
|
||
} catch (error) {
|
||
logger.error(error)
|
||
}
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.error {
|
||
margin-top: 8px;
|
||
padding: 5px;
|
||
border-radius: var(--border-radius);
|
||
color: var(--color-primary-element-text);
|
||
background-color: var(--color-error);
|
||
width: initial;
|
||
}
|
||
|
||
.warning {
|
||
margin-top: 8px;
|
||
padding: 5px;
|
||
border-radius: var(--border-radius);
|
||
color: var(--color-primary-element-text);
|
||
background-color: var(--color-warning);
|
||
width: initial;
|
||
}
|
||
|
||
.ajaxSwitch {
|
||
margin-top: 1rem;
|
||
}
|
||
</style>
|