1
1
mirror of https://github.com/n8n-io/n8n.git synced 2024-09-20 09:27:44 +03:00

Improve workflow retry

This commit is contained in:
Jan Oberhauser 2019-08-09 07:37:10 +02:00
parent d59a043e3f
commit 886100eeef
9 changed files with 38 additions and 25 deletions

View File

@ -4,10 +4,10 @@ import {
import {
createDeferredPromise,
IExecutionsCurrentSummary,
} from 'n8n-core';
import {
IExecutionsCurrentSummary,
IExecutingWorkflowData,
IWorkflowExecutionDataProcess,
} from '.';
@ -131,6 +131,7 @@ export class ActiveExecutions {
returnData.push(
{
id,
retryOf: data.executionData.retryOf as string | undefined,
startedAt: data.startedAt,
mode: data.executionData.executionMode,
workflowId: data.executionData.workflowData.id! as string,

View File

@ -162,8 +162,8 @@ export interface IExecutionsStopData {
export interface IExecutionsSummary {
id?: string; // executionIdDb
idActive?: string; // executionIdActive
mode: WorkflowExecuteMode;
finished?: boolean;
mode: WorkflowExecuteMode;
retryOf?: string;
retrySuccessId?: string;
startedAt: Date;
@ -172,6 +172,16 @@ export interface IExecutionsSummary {
workflowName?: string;
}
export interface IExecutionsCurrentSummary {
id: string;
retryOf?: string;
startedAt: Date;
mode: WorkflowExecuteMode;
workflowId: string;
}
export interface IExecutionDeleteFilter {
deleteBefore?: Date;
filters?: IDataObject;
@ -260,6 +270,7 @@ export interface IPushDataExecutionFinished {
data: IRun;
executionIdActive: string;
executionIdDb?: string;
retryOf?: string;
}
export interface IPushDataExecutionStarted {

View File

@ -828,7 +828,7 @@ class App {
// Retries a failed execution
this.app.post('/rest/executions/:id/retry', ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<string> => {
this.app.post('/rest/executions/:id/retry', ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<boolean> => {
// Get the data to execute
const fullExecutionDataFlatted = await Db.collections.Execution!.findOne(req.params.id);
@ -859,7 +859,13 @@ class App {
const workflowRunner = new WorkflowRunner();
const executionId = await workflowRunner.run(data);
return executionId;
const executionData = await this.activeExecutionsInstance.getPostExecutePromise(executionId);
if (executionData === undefined) {
throw new Error('The retry did not start for an unknown reason.');
}
return !!executionData.finished;
}));
@ -893,7 +899,6 @@ class App {
// Returns all the currently working executions
// this.app.get('/rest/executions-current', ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<IExecutionsCurrentSummaryExtended[]> => {
this.app.get('/rest/executions-current', ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<IExecutionsSummary[]> => {
const executingWorkflows = this.activeExecutionsInstance.getActiveExecutions();
@ -912,7 +917,8 @@ class App {
{
idActive: data.id.toString(),
workflowId: data.workflowId,
mode:data.mode,
mode: data.mode,
retryOf: data.retryOf,
startedAt: new Date(data.startedAt),
}
);

View File

@ -67,7 +67,7 @@ function executeErrorWorkflow(workflowData: IWorkflowBase, fullRunData: IRun, mo
* @param {string} executionIdActive The id of the finished execution
* @param {string} [executionIdDb] The database id of finished execution
*/
export function pushExecutionFinished(fullRunData: IRun, executionIdActive: string, executionIdDb?: string) {
export function pushExecutionFinished(fullRunData: IRun, executionIdActive: string, executionIdDb?: string, retryOf?: string) {
// Clone the object except the runData. That one is not supposed
// to be send. Because that data got send piece by piece after
// each node which finished executing
@ -87,6 +87,7 @@ export function pushExecutionFinished(fullRunData: IRun, executionIdActive: stri
executionIdActive,
executionIdDb,
data: pushRunData,
retryOf,
};
pushInstance.send('executionFinished', sendData);
@ -166,7 +167,7 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, execution
}
if (mode === 'manual' && saveManualExecutions === false) {
pushExecutionFinished(fullRunData, executionId);
pushExecutionFinished(fullRunData, executionId, undefined, retryOf);
executeErrorWorkflow(workflowData, fullRunData, mode);
return;
}
@ -183,7 +184,7 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, execution
if (workflowDidSucceed === true && saveDataSuccessExecution === 'none' ||
workflowDidSucceed === false && saveDataErrorExecution === 'none'
) {
pushExecutionFinished(fullRunData, executionId);
pushExecutionFinished(fullRunData, executionId, undefined, retryOf);
executeErrorWorkflow(workflowData, fullRunData, mode);
return;
}
@ -216,10 +217,10 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, execution
await Db.collections.Execution!.update(retryOf, { retrySuccessId: executionResult.id });
}
pushExecutionFinished(fullRunData, executionId, executionResult.id as string);
pushExecutionFinished(fullRunData, executionId, executionResult.id as string, retryOf);
executeErrorWorkflow(workflowData, fullRunData, mode, executionResult ? executionResult.id as string : undefined);
} catch (error) {
pushExecutionFinished(fullRunData, executionId);
pushExecutionFinished(fullRunData, executionId, undefined, retryOf);
executeErrorWorkflow(workflowData, fullRunData, mode);
}
},

View File

@ -46,13 +46,6 @@ export interface IExecuteSingleFunctions extends IExecuteSingleFunctionsBase {
}
export interface IExecutionsCurrentSummary {
id: string;
startedAt: Date;
mode: WorkflowExecuteMode;
workflowId: string;
}
export interface ITriggerFunctions extends ITriggerFunctionsBase {
helpers: {
prepareBinaryData(binaryData: Buffer, filePath?: string, mimeType?: string): Promise<IBinaryData>;

View File

@ -143,7 +143,7 @@ export interface IRestApi {
getCredentialTypes(): Promise<ICredentialType[]>;
getExecution(id: string): Promise<IExecutionResponse>;
deleteExecutions(sendData: IExecutionDeleteFilter): Promise<void>;
retryExecution(id: string): Promise<IExecutionResponse>;
retryExecution(id: string): Promise<boolean>;
getTimezones(): Promise<IDataObject>;
}
@ -303,6 +303,8 @@ export interface IExecutionsCurrentSummaryExtended {
idActive: string;
finished?: boolean;
mode: WorkflowExecuteMode;
retryOf?: string;
retrySuccessId?: string;
startedAt: Date;
stoppedAt?: Date;
workflowId: string;
@ -356,6 +358,7 @@ export interface IPushDataExecutionFinished {
data: IRun;
executionIdActive: string;
executionIdDb?: string;
retryOf?: string;
}
export interface IPushDataExecutionStarted {

View File

@ -390,9 +390,9 @@ export default mixins(
this.isDataLoading = true;
try {
const data = await this.restApi().retryExecution(execution.id);
const retrySuccessful = await this.restApi().retryExecution(execution.id);
if (data.finished === true) {
if (retrySuccessful === true) {
this.$showMessage({
title: 'Retry successful',
message: 'The retry was successful!',
@ -406,13 +406,11 @@ export default mixins(
});
}
this.refreshData();
this.isDataLoading = false;
} catch (error) {
this.$showError(error, 'Problem with retry', 'There was a problem with the retry:');
this.isDataLoading = false;
this.refreshData();
}
},
async refreshData () {

View File

@ -160,7 +160,6 @@ export const pushConnection = mixins(
const runDataExecuted = pushData.data;
if (runDataExecuted.finished !== true) {
// There was a problem with executing the workflow
let errorMessage = 'There was a problem executing the workflow!';
@ -202,6 +201,7 @@ export const pushConnection = mixins(
finished: false,
mode: pushData.mode,
startedAt: pushData.startedAt,
retryOf: pushData.retryOf,
workflowId: pushData.workflowId,
workflowName: pushData.workflowName,
};

View File

@ -263,7 +263,7 @@ export const restApi = Vue.extend({
},
// Returns the execution with the given name
retryExecution: (id: string): Promise<IExecutionResponse> => {
retryExecution: (id: string): Promise<boolean> => {
return self.restApi().makeRestApiRequest('POST', `/executions/${id}/retry`);
},