fix(core): Fixes event msg confirmations if no subscribers present (#5118)

* adds ExecutionEvents view modal to ExecutionList

* fix time rendering and remove wf column

* checks for unfinished executions and fails them

* prevent re-setting stoppedAt for execution

* removing UI changes but keeping eventbus fixes

* remove comment
This commit is contained in:
Michael Auerswald
2023-01-11 14:09:09 +01:00
committed by GitHub
parent 044b153275
commit 62d06b1e6e
10 changed files with 272 additions and 70 deletions

View File

@@ -28,6 +28,12 @@ interface MessageEventBusLogWriterOptions {
maxFileSizeInKB?: number;
}
interface ReadMessagesFromLogFileResult {
loggedMessages: EventMessageTypes[];
sentMessages: EventMessageTypes[];
unfinishedExecutions: Set<string>;
}
/**
* MessageEventBusWriter for Files
*/
@@ -138,45 +144,31 @@ export class MessageEventBusLogWriter {
async getMessages(
mode: EventMessageReturnMode = 'all',
includePreviousLog = true,
): Promise<EventMessageTypes[]> {
const logFileName0 = await MessageEventBusLogWriter.instance.getThread()?.getLogFileName();
const logFileName1 = includePreviousLog
? await MessageEventBusLogWriter.instance.getThread()?.getLogFileName(1)
: undefined;
const results: {
loggedMessages: EventMessageTypes[];
sentMessages: EventMessageTypes[];
} = {
logHistory = 1,
): Promise<ReadMessagesFromLogFileResult> {
const results: ReadMessagesFromLogFileResult = {
loggedMessages: [],
sentMessages: [],
unfinishedExecutions: new Set<string>(),
};
if (logFileName0) {
await this.readLoggedMessagesFromFile(results, mode, logFileName0);
}
if (logFileName1) {
await this.readLoggedMessagesFromFile(results, mode, logFileName1);
}
switch (mode) {
case 'all':
case 'unsent':
return results.loggedMessages;
case 'sent':
return results.sentMessages;
const logCount = logHistory
? Math.min(config.get('eventBus.logWriter.keepLogCount') as number, logHistory)
: (config.get('eventBus.logWriter.keepLogCount') as number);
for (let i = logCount; i >= 0; i--) {
const logFileName = await MessageEventBusLogWriter.instance.getThread()?.getLogFileName(i);
if (logFileName) {
await this.readLoggedMessagesFromFile(results, mode, logFileName);
}
}
return results;
}
async readLoggedMessagesFromFile(
results: {
loggedMessages: EventMessageTypes[];
sentMessages: EventMessageTypes[];
},
results: ReadMessagesFromLogFileResult,
mode: EventMessageReturnMode,
logFileName: string,
): Promise<{
loggedMessages: EventMessageTypes[];
sentMessages: EventMessageTypes[];
}> {
): Promise<ReadMessagesFromLogFileResult> {
if (logFileName && existsSync(logFileName)) {
try {
const rl = readline.createInterface({
@@ -189,6 +181,15 @@ export class MessageEventBusLogWriter {
if (isEventMessageOptions(json) && json.__type !== undefined) {
const msg = getEventMessageObjectByType(json);
if (msg !== null) results.loggedMessages.push(msg);
if (msg?.eventName === 'n8n.workflow.started' && msg?.payload?.executionId) {
results.unfinishedExecutions.add(msg?.payload?.executionId as string);
} else if (
(msg?.eventName === 'n8n.workflow.success' ||
msg?.eventName === 'n8n.workflow.failed') &&
msg?.payload?.executionId
) {
results.unfinishedExecutions.delete(msg?.payload?.executionId as string);
}
}
if (isEventMessageConfirm(json) && mode !== 'all') {
const removedMessage = remove(results.loggedMessages, (e) => e.id === json.confirm);
@@ -211,11 +212,84 @@ export class MessageEventBusLogWriter {
return results;
}
async getMessagesByExecutionId(
executionId: string,
logHistory?: number,
): Promise<EventMessageTypes[]> {
const result: EventMessageTypes[] = [];
const logCount = logHistory
? Math.min(config.get('eventBus.logWriter.keepLogCount') as number, logHistory)
: (config.get('eventBus.logWriter.keepLogCount') as number);
for (let i = 0; i < logCount; i++) {
const logFileName = await MessageEventBusLogWriter.instance.getThread()?.getLogFileName(i);
if (logFileName) {
result.push(...(await this.readFromFileByExecutionId(executionId, logFileName)));
}
}
return result.sort((a, b) => a.ts.diff(b.ts).toMillis());
}
async readFromFileByExecutionId(
executionId: string,
logFileName: string,
): Promise<EventMessageTypes[]> {
const messages: EventMessageTypes[] = [];
if (logFileName && existsSync(logFileName)) {
try {
const rl = readline.createInterface({
input: createReadStream(logFileName),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
try {
const json = jsonParse(line);
if (
isEventMessageOptions(json) &&
json.__type !== undefined &&
json.payload?.executionId === executionId
) {
const msg = getEventMessageObjectByType(json);
if (msg !== null) messages.push(msg);
}
} catch {
LoggerProxy.error(
`Error reading line messages from file: ${logFileName}, line: ${line}`,
);
}
});
// wait for stream to finish before continue
await eventOnce(rl, 'close');
} catch {
LoggerProxy.error(`Error reading logged messages from file: ${logFileName}`);
}
}
return messages;
}
async getMessagesAll(): Promise<EventMessageTypes[]> {
return (await this.getMessages('all')).loggedMessages;
}
async getMessagesSent(): Promise<EventMessageTypes[]> {
return this.getMessages('sent');
return (await this.getMessages('sent')).sentMessages;
}
async getMessagesUnsent(): Promise<EventMessageTypes[]> {
return this.getMessages('unsent');
return (await this.getMessages('unsent')).loggedMessages;
}
async getUnfinishedExecutions(): Promise<Set<string>> {
return (await this.getMessages('unfinished')).unfinishedExecutions;
}
async getUnsentAndUnfinishedExecutions(): Promise<{
unsentMessages: EventMessageTypes[];
unfinishedExecutions: Set<string>;
}> {
const result = await this.getMessages('unsent');
return {
unsentMessages: result.loggedMessages,
unfinishedExecutions: result.unfinishedExecutions,
};
}
}