mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-20 11:22:15 +00:00
✨ Make it possible to define if workflow executions should be
saved or not
This commit is contained in:
@@ -22,6 +22,15 @@ module.exports = {
|
||||
},
|
||||
|
||||
executions: {
|
||||
// If a workflow executes all the data gets saved by default. This
|
||||
// could be a problem when a workflow gets executed a lot and processes
|
||||
// a lot of data. To not write the database full it is possible to
|
||||
// not save the execution at all.
|
||||
// Depending on if the execution did succeed or error a different
|
||||
// save behaviour can be set.
|
||||
saveDataErrorExecution: 'all', // Available options: all, none
|
||||
saveDataSuccessExecution: 'all', // Available options: all, none
|
||||
|
||||
// If the executions of workflows which got started via the editor
|
||||
// should be saved. By default they will not be saved as this runs
|
||||
// are normally only for testing and debugging. This setting can
|
||||
|
||||
@@ -189,6 +189,8 @@ export interface IN8nConfigNodes {
|
||||
export interface IN8nUISettings {
|
||||
endpointWebhook: string;
|
||||
endpointWebhookTest: string;
|
||||
saveDataErrorExecution: string;
|
||||
saveDataSuccessExecution: string;
|
||||
saveManualExecutions: boolean;
|
||||
timezone: string;
|
||||
urlBaseWebhook: string;
|
||||
|
||||
@@ -73,6 +73,8 @@ class App {
|
||||
testWebhooks: TestWebhooks.TestWebhooks;
|
||||
endpointWebhook: string;
|
||||
endpointWebhookTest: string;
|
||||
saveDataErrorExecution: string;
|
||||
saveDataSuccessExecution: string;
|
||||
saveManualExecutions: boolean;
|
||||
timezone: string;
|
||||
activeExecutionsInstance: ActiveExecutions.ActiveExecutions;
|
||||
@@ -83,6 +85,8 @@ class App {
|
||||
|
||||
this.endpointWebhook = config.get('urls.endpointWebhook') as string;
|
||||
this.endpointWebhookTest = config.get('urls.endpointWebhookTest') as string;
|
||||
this.saveDataErrorExecution = config.get('executions.saveDataErrorExecution') as string;
|
||||
this.saveDataSuccessExecution = config.get('executions.saveDataSuccessExecution') as string;
|
||||
this.saveManualExecutions = config.get('executions.saveManualExecutions') as boolean;
|
||||
this.timezone = config.get('timezone') as string;
|
||||
|
||||
@@ -271,6 +275,14 @@ class App {
|
||||
// Do not save the default timezone
|
||||
delete newWorkflowData.settings.timezone;
|
||||
}
|
||||
if (newWorkflowData.settings.saveDataErrorExecution === 'DEFAULT') {
|
||||
// Do not save when default got set
|
||||
delete newWorkflowData.settings.saveDataErrorExecution;
|
||||
}
|
||||
if (newWorkflowData.settings.saveDataSuccessExecution === 'DEFAULT') {
|
||||
// Do not save when default got set
|
||||
delete newWorkflowData.settings.saveDataSuccessExecution;
|
||||
}
|
||||
if (newWorkflowData.settings.saveManualExecutions === 'DEFAULT') {
|
||||
// Do not save when default got set
|
||||
delete newWorkflowData.settings.saveManualExecutions;
|
||||
@@ -900,6 +912,8 @@ class App {
|
||||
return {
|
||||
endpointWebhook: this.endpointWebhook,
|
||||
endpointWebhookTest: this.endpointWebhookTest,
|
||||
saveDataErrorExecution: this.saveDataErrorExecution,
|
||||
saveDataSuccessExecution: this.saveDataSuccessExecution,
|
||||
saveManualExecutions: this.saveManualExecutions,
|
||||
timezone: this.timezone,
|
||||
urlBaseWebhook: WebhookHelpers.getWebhookBaseUrl(),
|
||||
|
||||
@@ -132,18 +132,26 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, workflowI
|
||||
await workflowSavePromise;
|
||||
}
|
||||
|
||||
// For now do not save manual executions
|
||||
// TODO: Later that should be configurable. Think about what to do
|
||||
// with the workflow.id when not saved yet or currently differes from saved version (save diff?!?!)
|
||||
|
||||
executeErrorWorkflow(workflowData, fullRunData, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Should maybe have different log-modes like
|
||||
// to save all data, only first input, only last node output, ....
|
||||
// or depending on success to only save all on error to be
|
||||
// able to start it again where it ended (but would then also have to save active data)
|
||||
// Check config to know if execution should be saved or not
|
||||
let saveDataErrorExecution = config.get('executions.saveDataErrorExecution') as string;
|
||||
let saveDataSuccessExecution = config.get('executions.saveDataSuccessExecution') as string;
|
||||
if (workflowInstance.settings !== undefined) {
|
||||
saveDataErrorExecution = (workflowInstance.settings.saveDataErrorExecution as string) || saveDataErrorExecution;
|
||||
saveDataSuccessExecution = (workflowInstance.settings.saveDataSuccessExecution as string) || saveDataSuccessExecution;
|
||||
}
|
||||
|
||||
const workflowDidSucceed = !fullRunData.data.resultData.error;
|
||||
if (workflowDidSucceed === true && saveDataSuccessExecution === 'none' ||
|
||||
workflowDidSucceed === false && saveDataErrorExecution === 'none'
|
||||
) {
|
||||
executeErrorWorkflow(workflowData, fullRunData, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
const fullExecutionData: IExecutionDb = {
|
||||
data: fullRunData.data,
|
||||
mode: fullRunData.mode,
|
||||
|
||||
@@ -358,6 +358,8 @@ export interface IPushDataTestWebhook {
|
||||
export interface IN8nUISettings {
|
||||
endpointWebhook: string;
|
||||
endpointWebhookTest: string;
|
||||
saveDataErrorExecution: string;
|
||||
saveDataSuccessExecution: string;
|
||||
saveManualExecutions: boolean;
|
||||
timezone: string;
|
||||
urlBaseWebhook: string;
|
||||
@@ -365,6 +367,8 @@ export interface IN8nUISettings {
|
||||
|
||||
export interface IWorkflowSettings extends IWorkflowSettingsWorkflow {
|
||||
errorWorkflow?: string;
|
||||
saveDataErrorExecution?: string;
|
||||
saveDataSuccessExecution?: string;
|
||||
saveManualExecutions?: boolean;
|
||||
timezone?: string;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,44 @@
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="10" class="setting-name">
|
||||
Save Data Error Execution:
|
||||
<el-tooltip class="setting-info" placement="top" effect="light">
|
||||
<div slot="content" v-html="helpTexts.saveDataErrorExecution"></div>
|
||||
<font-awesome-icon icon="question-circle" />
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="14" class="ignore-key-press">
|
||||
<el-select v-model="workflowSettings.saveDataErrorExecution" placeholder="Select Option" size="small" filterable>
|
||||
<el-option
|
||||
v-for="option of saveDataErrorExecutionOptions"
|
||||
:key="option.key"
|
||||
:label="option.value"
|
||||
:value="option.key">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="10" class="setting-name">
|
||||
Save Data Success Execution:
|
||||
<el-tooltip class="setting-info" placement="top" effect="light">
|
||||
<div slot="content" v-html="helpTexts.saveDataSuccessExecution"></div>
|
||||
<font-awesome-icon icon="question-circle" />
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="14" class="ignore-key-press">
|
||||
<el-select v-model="workflowSettings.saveDataSuccessExecution" placeholder="Select Option" size="small" filterable>
|
||||
<el-option
|
||||
v-for="option of saveDataSuccessExecutionOptions"
|
||||
:key="option.key"
|
||||
:label="option.value"
|
||||
:value="option.key">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="10" class="setting-name">
|
||||
Save Manual Executions:
|
||||
@@ -77,8 +115,9 @@ import { restApi } from '@/components/mixins/restApi';
|
||||
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
||||
import { showMessage } from '@/components/mixins/showMessage';
|
||||
import {
|
||||
IWorkflowShortResponse,
|
||||
IWorkflowDataUpdate,
|
||||
IWorkflowSettings,
|
||||
IWorkflowShortResponse,
|
||||
} from '@/Interface';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
@@ -98,12 +137,18 @@ export default mixins(
|
||||
helpTexts: {
|
||||
errorWorkflow: 'The workflow to run in case the current one fails.<br />To function correctly that workflow has to contain an "Error Trigger" node!',
|
||||
timezone: 'The timezone in which the workflow should run. Gets for example used by "Cron" node.',
|
||||
saveDataErrorExecution: 'If data data of executions should be saved in case they failed.',
|
||||
saveDataSuccessExecution: 'If data data of executions should be saved in case they succeed.',
|
||||
saveManualExecutions: 'If data data of executions should be saved when started manually from the editor.',
|
||||
},
|
||||
defaultValues: {
|
||||
timezone: 'America/New_York',
|
||||
saveDataErrorExecution: 'all',
|
||||
saveDataSuccessExecution: 'all',
|
||||
saveManualExecutions: false,
|
||||
},
|
||||
saveDataErrorExecutionOptions: [] as Array<{ key: string, value: string }>,
|
||||
saveDataSuccessExecutionOptions: [] as Array<{ key: string, value: string }>,
|
||||
saveManualOptions: [] as Array<{ key: string | boolean, value: string }>,
|
||||
timezones: [] as Array<{ key: string, value: string }>,
|
||||
workflowSettings: {},
|
||||
@@ -124,11 +169,49 @@ export default mixins(
|
||||
this.$emit('closeDialog');
|
||||
return false;
|
||||
},
|
||||
async loadSaveDataErrorExecutionOptions () {
|
||||
this.saveDataErrorExecutionOptions.length = 0;
|
||||
this.saveDataErrorExecutionOptions.push.apply(
|
||||
this.saveDataErrorExecutionOptions, [
|
||||
{
|
||||
key: 'DEFAULT',
|
||||
value: 'Default - ' + (this.defaultValues.saveDataErrorExecution === 'all' ? 'Save' : 'Do not save'),
|
||||
},
|
||||
{
|
||||
key: 'all',
|
||||
value: 'Save',
|
||||
},
|
||||
{
|
||||
key: 'none',
|
||||
value: 'Do not save',
|
||||
}
|
||||
]
|
||||
);
|
||||
},
|
||||
async loadSaveDataSuccessExecutionOptions () {
|
||||
this.saveDataSuccessExecutionOptions.length = 0;
|
||||
this.saveDataSuccessExecutionOptions.push.apply(
|
||||
this.saveDataSuccessExecutionOptions, [
|
||||
{
|
||||
key: 'DEFAULT',
|
||||
value: 'Default - ' + (this.defaultValues.saveDataSuccessExecution === 'all' ? 'Save' : 'Do not save'),
|
||||
},
|
||||
{
|
||||
key: 'all',
|
||||
value: 'Save',
|
||||
},
|
||||
{
|
||||
key: 'none',
|
||||
value: 'Do not save',
|
||||
}
|
||||
]
|
||||
);
|
||||
},
|
||||
async loadSaveManualOptions () {
|
||||
this.saveManualOptions.length = 0;
|
||||
this.saveManualOptions.push({
|
||||
key: 'DEFAULT',
|
||||
value: 'Use default - ' + (this.defaultValues.saveManualExecutions === true ? 'Yes' : 'No'),
|
||||
value: 'Default - ' + (this.defaultValues.saveManualExecutions === true ? 'Yes' : 'No'),
|
||||
});
|
||||
this.saveManualOptions.push({
|
||||
key: true,
|
||||
@@ -139,6 +222,7 @@ export default mixins(
|
||||
value: 'No',
|
||||
});
|
||||
},
|
||||
|
||||
async loadTimezones () {
|
||||
if (this.timezones.length !== 0) {
|
||||
// Data got already loaded
|
||||
@@ -196,12 +280,16 @@ export default mixins(
|
||||
return;
|
||||
}
|
||||
|
||||
this.defaultValues.saveDataErrorExecution = this.$store.getters.saveDataErrorExecution;
|
||||
this.defaultValues.saveDataSuccessExecution = this.$store.getters.saveDataSuccessExecution;
|
||||
this.defaultValues.saveManualExecutions = this.$store.getters.saveManualExecutions;
|
||||
this.defaultValues.timezone = this.$store.getters.timezone;
|
||||
|
||||
this.isLoading = true;
|
||||
const promises = [];
|
||||
promises.push(this.loadWorkflows());
|
||||
promises.push(this.loadSaveDataErrorExecutionOptions());
|
||||
promises.push(this.loadSaveDataSuccessExecutionOptions());
|
||||
promises.push(this.loadSaveManualOptions());
|
||||
promises.push(this.loadTimezones());
|
||||
|
||||
@@ -216,6 +304,12 @@ export default mixins(
|
||||
if (workflowSettings.timezone === undefined) {
|
||||
workflowSettings.timezone = 'DEFAULT';
|
||||
}
|
||||
if (workflowSettings.saveDataErrorExecution === undefined) {
|
||||
workflowSettings.saveDataErrorExecution = 'DEFAULT';
|
||||
}
|
||||
if (workflowSettings.saveDataSuccessExecution === undefined) {
|
||||
workflowSettings.saveDataSuccessExecution = 'DEFAULT';
|
||||
}
|
||||
if (workflowSettings.saveManualExecutions === undefined) {
|
||||
workflowSettings.saveManualExecutions = 'DEFAULT';
|
||||
}
|
||||
@@ -238,7 +332,16 @@ export default mixins(
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
this.$store.commit('setWorkflowSettings', this.workflowSettings);
|
||||
|
||||
// Get the settings without the defaults set for local workflow settings
|
||||
const localWorkflowSettings: IWorkflowSettings = {};
|
||||
for (const key of Object.keys(this.workflowSettings)) {
|
||||
if (this.workflowSettings[key] !== 'DEFAULT') {
|
||||
localWorkflowSettings[key] = this.workflowSettings[key];
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.commit('setWorkflowSettings', localWorkflowSettings);
|
||||
|
||||
this.isLoading = false;
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ export const store = new Vuex.Store({
|
||||
executingNode: '' as string | null,
|
||||
executionWaitingForWebhook: false,
|
||||
pushConnectionActive: false,
|
||||
saveDataErrorExecution: 'all',
|
||||
saveDataSuccessExecution: 'all',
|
||||
saveManualExecutions: false,
|
||||
timezone: 'America/New_York',
|
||||
workflowExecutionData: null as IExecutionResponse | null,
|
||||
@@ -458,6 +460,12 @@ export const store = new Vuex.Store({
|
||||
Vue.set(state, 'endpointWebhookTest', endpointWebhookTest);
|
||||
},
|
||||
|
||||
setSaveDataErrorExecution(state, newValue: string) {
|
||||
Vue.set(state, 'saveDataErrorExecution', newValue);
|
||||
},
|
||||
setSaveDataSuccessExecution(state, newValue: string) {
|
||||
Vue.set(state, 'saveDataSuccessExecution', newValue);
|
||||
},
|
||||
setSaveManualExecutions (state, saveManualExecutions: boolean) {
|
||||
Vue.set(state, 'saveManualExecutions', saveManualExecutions);
|
||||
},
|
||||
@@ -551,6 +559,12 @@ export const store = new Vuex.Store({
|
||||
return `${state.urlBaseWebhook}${state.endpointWebhookTest}`;
|
||||
},
|
||||
|
||||
saveDataErrorExecution: (state): string => {
|
||||
return state.saveDataErrorExecution;
|
||||
},
|
||||
saveDataSuccessExecution: (state): string => {
|
||||
return state.saveDataSuccessExecution;
|
||||
},
|
||||
saveManualExecutions: (state): boolean => {
|
||||
return state.saveManualExecutions;
|
||||
},
|
||||
|
||||
@@ -1674,9 +1674,12 @@ export default mixins(
|
||||
},
|
||||
async loadSettings (): Promise<void> {
|
||||
const settings = await this.restApi().getSettings() as IN8nUISettings;
|
||||
|
||||
this.$store.commit('setUrlBaseWebhook', settings.urlBaseWebhook);
|
||||
this.$store.commit('setEndpointWebhook', settings.endpointWebhook);
|
||||
this.$store.commit('setEndpointWebhookTest', settings.endpointWebhookTest);
|
||||
this.$store.commit('setSaveDataErrorExecution', settings.saveDataErrorExecution);
|
||||
this.$store.commit('setSaveDataSuccessExecution', settings.saveDataSuccessExecution);
|
||||
this.$store.commit('setSaveManualExecutions', settings.saveManualExecutions);
|
||||
this.$store.commit('setTimezone', settings.timezone);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user