feat(core): Make Redis available for backend communication (#6719)

* support redis cluster

* cleanup, fix config schema

* set default prefix to bull

* initial commit

* improve logging

* improve types and refactor

* list support and refactor

* fix redis service and tests

* add comment

* add redis and cache prefix

* use injection

* lint fix

* clean schema comments

* improve naming, tests, cluster client

* merge master

* cache returns unknown instead of T

* update cache service, tests and doc

* remove console.log

* do not cache null or undefined values

* fix merge

* lint fix
This commit is contained in:
Michael Auerswald
2023-08-02 12:51:25 +02:00
committed by GitHub
parent 4ac4b850dd
commit 3cad60e918
20 changed files with 1377 additions and 322 deletions

View File

@@ -1,11 +1,16 @@
import type Bull from 'bull';
import { type RedisOptions } from 'ioredis';
import { Service } from 'typedi';
import { LoggerProxy, type IExecuteResponsePromiseData } from 'n8n-workflow';
import config from '@/config';
import { type IExecuteResponsePromiseData } from 'n8n-workflow';
import { ActiveExecutions } from '@/ActiveExecutions';
import * as WebhookHelpers from '@/WebhookHelpers';
import { getRedisClusterNodes, getRedisPrefix } from './GenericHelpers';
import {
getRedisClusterClient,
getRedisClusterNodes,
getRedisPrefix,
getRedisStandardClient,
} from './services/redis/RedisServiceHelper';
import type { RedisClientType } from './services/redis/RedisServiceBaseClasses';
import config from '@/config';
export type JobId = Bull.JobId;
export type Job = Bull.Job<JobData>;
@@ -32,10 +37,10 @@ export class Queue {
constructor(private activeExecutions: ActiveExecutions) {}
async init() {
const prefix = getRedisPrefix();
const bullPrefix = config.getEnv('queue.bull.prefix');
const prefix = getRedisPrefix(bullPrefix);
const clusterNodes = getRedisClusterNodes();
const usesRedisCluster = clusterNodes.length > 0;
const { host, port, username, password, db }: RedisOptions = config.getEnv('queue.bull.redis');
// eslint-disable-next-line @typescript-eslint/naming-convention
const { default: Bull } = await import('bull');
// eslint-disable-next-line @typescript-eslint/naming-convention
@@ -45,40 +50,12 @@ export class Queue {
// for some time. With it enabled, worker might take minutes to realize
// redis is back up and resume working.
// More here: https://github.com/OptimalBits/bull/issues/890
LoggerProxy.debug(
usesRedisCluster
? `Initialising Redis cluster connection with nodes: ${clusterNodes
.map((e) => `${e.host}:${e.port}`)
.join(',')}`
: `Initialising Redis client connection with host: ${host ?? 'localhost'} and port: ${
port ?? '6379'
}`,
);
const sharedRedisOptions: RedisOptions = {
username,
password,
db,
enableReadyCheck: false,
maxRetriesPerRequest: null,
};
this.jobQueue = new Bull('jobs', {
prefix,
createClient: (type, clientConfig) =>
usesRedisCluster
? new Redis.Cluster(
clusterNodes.map((node) => ({ host: node.host, port: node.port })),
{
...clientConfig,
redisOptions: sharedRedisOptions,
},
)
: new Redis({
...clientConfig,
host,
port,
...sharedRedisOptions,
}),
? getRedisClusterClient(Redis, clientConfig, (type + '(bull)') as RedisClientType)
: getRedisStandardClient(Redis, clientConfig, (type + '(bull)') as RedisClientType),
});
this.jobQueue.on('global:progress', (jobId, progress: WebhookResponse) => {