Midday / packages /cache /src /shared-redis.ts
Jules
Final deployment with all fixes and verified content
c09f67c
import { createLoggerWithContext } from "@midday/logger";
const logger = createLoggerWithContext("redis");
let sharedRedisClient: any = null;
let RedisClientClass: any = null;
// Dynamically load Bun's RedisClient to avoid crashing in non-Bun runtimes (e.g. trigger.dev on Node)
try {
({ RedisClient: RedisClientClass } = require("bun"));
} catch {
// Not running in Bun — cache will be unavailable
}
/**
* Resolve the Redis URL.
*
* All regions share a single Upstash Redis instance via REDIS_URL.
*/
function resolveRedisUrl(): string | undefined {
return process.env.REDIS_URL;
}
/**
* Get or create a shared Redis client instance.
* Returns null in non-Bun runtimes where RedisClient is unavailable.
*/
export function getSharedRedisClient(): any {
if (sharedRedisClient) {
return sharedRedisClient;
}
if (!RedisClientClass) {
return null;
}
const redisUrl = resolveRedisUrl();
if (!redisUrl) {
throw new Error(
"Redis URL not found. Set per-region REDIS_CACHE_* env vars or REDIS_URL.",
);
}
const isProduction =
process.env.NODE_ENV === "production" ||
process.env.RAILWAY_ENVIRONMENT === "production";
sharedRedisClient = new RedisClientClass(redisUrl, {
connectionTimeout: isProduction ? 10000 : 5000,
autoReconnect: true,
maxRetries: 10,
enableOfflineQueue: true,
enableAutoPipelining: true,
});
sharedRedisClient.onclose = (err: Error) => {
if (err) {
logger.error("Connection closed", { error: err.message });
}
};
// Connect eagerly so the client is ready for first use
sharedRedisClient.connect().catch((err: Error) => {
logger.error("Initial connection error", { error: err.message });
});
return sharedRedisClient;
}