feat(API): Report unhandled app crashes to Sentry (#4548)

* SIGTERM/SIGINT should only be handled once

* move error-handling initialization to commands

* create a new `sleep` function in workflow utils

* detect crashes and report them to Sentry
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2022-11-08 17:06:00 +01:00
committed by GitHub
parent 5d852f9230
commit 2425c10b2b
17 changed files with 129 additions and 73 deletions

View File

@@ -7,6 +7,7 @@ import {
jsonParse,
NodeApiError,
NodeOperationError,
sleep,
} from 'n8n-workflow';
import { DiscordAttachment, DiscordWebhook } from './Interfaces';
@@ -244,7 +245,7 @@ export class Discord implements INodeType {
// remaining requests 0
// https://discord.com/developers/docs/topics/rate-limits
if (!+remainingRatelimit) {
await new Promise<void>((resolve) => setTimeout(resolve, resetAfter || 1000));
await sleep(resetAfter ?? 1000);
}
break;
@@ -255,7 +256,7 @@ export class Discord implements INodeType {
if (error.statusCode === 429) {
const retryAfter = error.response?.headers['retry-after'] || 1000;
await new Promise<void>((resolve) => setTimeout(resolve, +retryAfter));
await sleep(+retryAfter);
continue;
}

View File

@@ -10,6 +10,7 @@ import {
INodeTypeDescription,
NodeApiError,
NodeOperationError,
sleep,
} from 'n8n-workflow';
import { OptionsWithUri } from 'request';
@@ -667,7 +668,7 @@ export class HttpRequestV1 implements INodeType {
const batchSize: number =
(options.batchSize as number) > 0 ? (options.batchSize as number) : 1;
if (itemIndex % batchSize === 0) {
await new Promise((resolve) => setTimeout(resolve, options.batchInterval as number));
await sleep(options.batchInterval as number);
}
}

View File

@@ -8,6 +8,7 @@ import {
INodeTypeDescription,
NodeApiError,
NodeOperationError,
sleep,
} from 'n8n-workflow';
import { OptionsWithUri } from 'request';
@@ -701,7 +702,7 @@ export class HttpRequestV2 implements INodeType {
const batchSize: number =
(options.batchSize as number) > 0 ? (options.batchSize as number) : 1;
if (itemIndex % batchSize === 0) {
await new Promise((resolve) => setTimeout(resolve, options.batchInterval as number));
await sleep(options.batchInterval as number);
}
}

View File

@@ -9,6 +9,7 @@ import {
jsonParse,
NodeApiError,
NodeOperationError,
sleep,
} from 'n8n-workflow';
import { OptionsWithUri } from 'request-promise-native';
@@ -1002,7 +1003,7 @@ export class HttpRequestV3 implements INodeType {
if (itemIndex > 0 && batchSize >= 0 && batchInterval > 0) {
if (itemIndex % batchSize === 0) {
await new Promise((resolve) => setTimeout(resolve, batchInterval));
await sleep(batchInterval);
}
}

View File

@@ -1,4 +1,4 @@
import { IDataObject, IExecuteFunctions, ITriggerFunctions } from 'n8n-workflow';
import { IDataObject, IExecuteFunctions, ITriggerFunctions, sleep } from 'n8n-workflow';
import * as amqplib from 'amqplib';
@@ -138,9 +138,7 @@ export class MessageTracker {
// when for example a new version of the workflow got saved. That would lead to
// them getting delivered and processed again.
while (unansweredMessages !== 0 && count++ <= 300) {
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});
await sleep(1000);
unansweredMessages = this.unansweredMessages();
}

View File

@@ -13,6 +13,7 @@ import {
INodeExecutionData,
NodeApiError,
NodeOperationError,
sleep,
} from 'n8n-workflow';
export async function twitterApiRequest(
@@ -193,12 +194,7 @@ export async function uploadAttachments(
// data has not been uploaded yet, so wait for it to be ready
if (response.processing_info) {
const { check_after_secs } = response.processing_info as IDataObject;
await new Promise((resolve, _reject) => {
setTimeout(() => {
// @ts-ignore
resolve();
}, (check_after_secs as number) * 1000);
});
await sleep((check_after_secs as number) * 1000);
}
media.push(response);