redis-connection.tsβ’3.43 kB
import fs from 'fs'
import { AppSystemProp } from '@activepieces/server-shared'
import { isNil } from '@activepieces/shared'
import Redis, { RedisOptions } from 'ioredis'
import { RedisType, system } from '../helper/system/system'
const redisConnectionMode = system.getOrThrow(AppSystemProp.REDIS_TYPE)
const url = system.get(AppSystemProp.REDIS_URL)
const password = system.get(AppSystemProp.REDIS_PASSWORD)
const useSsl = system.getBoolean(AppSystemProp.REDIS_USE_SSL) ?? false
const sslCaFile = system.get(AppSystemProp.REDIS_SSL_CA_FILE)
const readCAFile = (file: string | undefined): string | undefined => {
if (isNil(file)) {
return undefined
}
return fs.readFileSync(file, { encoding: 'utf8' })
}
const createStandaloneClient = (config: Partial<RedisOptions>): Redis => {
const host = system.getOrThrow(AppSystemProp.REDIS_HOST)
const serializedPort = system.getOrThrow(AppSystemProp.REDIS_PORT)
const username = system.get(AppSystemProp.REDIS_USER)
const port = Number.parseInt(serializedPort, 10)
const db = system.getNumber(AppSystemProp.REDIS_DB) ?? 0
return new Redis({
...config,
host,
port,
username,
password,
db,
tls: useSsl ? {
ca: readCAFile(sslCaFile),
} : undefined,
})
}
export const createRedisClient = (params?: CreateRedisClientParams): Redis => {
const config: Partial<RedisOptions> = {
maxRetriesPerRequest: null,
...params,
}
if (url) {
return new Redis(url, {
...config,
})
}
switch (redisConnectionMode) {
case RedisType.SENTINEL:
return createSentinelClient(config)
case RedisType.DEFAULT:
default:
return createStandaloneClient(config)
}
}
const createSentinelClient = (config: Partial<RedisOptions>): Redis => {
const sentinelList = system.getOrThrow(AppSystemProp.REDIS_SENTINEL_HOSTS)
const sentinelName = system.getOrThrow(AppSystemProp.REDIS_SENTINEL_NAME)
const sentinelrole = system.get<'master' | 'slave'>(AppSystemProp.REDIS_SENTINEL_ROLE)
const username = system.get(AppSystemProp.REDIS_USER)
const sentinels = sentinelList.split(',').map((sentinel) => {
const [host, port] = sentinel.split(':')
return { host, port: Number.parseInt(port, 10) }
})
const tlsCa = readCAFile(sslCaFile)
const redisOptions: RedisOptions = {
...config,
...({ sentinels }),
name: sentinelName,
username,
password,
role: sentinelrole,
...getTlsOptionsForSentinel(useSsl, tlsCa),
lazyConnect: true,
}
return new Redis(redisOptions)
}
const getTlsOptionsForSentinel = (useSsl: boolean, tlsCa: string | undefined): Partial<RedisOptions> => {
if (!useSsl) {
return {}
}
return {
enableTLSForSentinelMode: true,
tls: {
ca: tlsCa,
},
sentinelTLS: {
ca: tlsCa,
},
}
}
type CreateRedisClientParams = {
/**
* connection timeout in milliseconds
*/
connectTimeout?: number
maxRetriesPerRequest?: number
}
export const getRedisConnection = (() => {
let redis: Redis | null = null
return (): Redis => {
if (!isNil(redis)) {
return redis
}
redis = createRedisClient()
return redis
}
})()