mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-22 14:10:45 -06:00
Compare commits
2 Commits
feat/progr
...
feature/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c16f7f9ed | ||
|
|
623efc28c7 |
@@ -1,97 +0,0 @@
|
|||||||
// This cache handler follows the @fortedigital/nextjs-cache-handler example
|
|
||||||
// Read more at: https://github.com/fortedigital/nextjs-cache-handler
|
|
||||||
|
|
||||||
// @neshca/cache-handler dependencies
|
|
||||||
const { CacheHandler } = require("@neshca/cache-handler");
|
|
||||||
const createLruHandler = require("@neshca/cache-handler/local-lru").default;
|
|
||||||
|
|
||||||
// Next/Redis dependencies
|
|
||||||
const { createClient } = require("redis");
|
|
||||||
const { PHASE_PRODUCTION_BUILD } = require("next/constants");
|
|
||||||
|
|
||||||
// @fortedigital/nextjs-cache-handler dependencies
|
|
||||||
const createRedisHandler = require("@fortedigital/nextjs-cache-handler/redis-strings").default;
|
|
||||||
const { Next15CacheHandler } = require("@fortedigital/nextjs-cache-handler/next-15-cache-handler");
|
|
||||||
|
|
||||||
// Usual onCreation from @neshca/cache-handler
|
|
||||||
CacheHandler.onCreation(() => {
|
|
||||||
// Important - It's recommended to use global scope to ensure only one Redis connection is made
|
|
||||||
// This ensures only one instance get created
|
|
||||||
if (global.cacheHandlerConfig) {
|
|
||||||
return global.cacheHandlerConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Important - It's recommended to use global scope to ensure only one Redis connection is made
|
|
||||||
// This ensures new instances are not created in a race condition
|
|
||||||
if (global.cacheHandlerConfigPromise) {
|
|
||||||
return global.cacheHandlerConfigPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If REDIS_URL is not set, we will use LRU cache only
|
|
||||||
if (!process.env.REDIS_URL) {
|
|
||||||
const lruCache = createLruHandler();
|
|
||||||
return { handlers: [lruCache] };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main promise initializing the handler
|
|
||||||
global.cacheHandlerConfigPromise = (async () => {
|
|
||||||
/** @type {import("redis").RedisClientType | null} */
|
|
||||||
let redisClient = null;
|
|
||||||
// eslint-disable-next-line turbo/no-undeclared-env-vars -- Next.js will inject this variable
|
|
||||||
if (PHASE_PRODUCTION_BUILD !== process.env.NEXT_PHASE) {
|
|
||||||
const settings = {
|
|
||||||
url: process.env.REDIS_URL, // Make sure you configure this variable
|
|
||||||
pingInterval: 10000,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
redisClient = createClient(settings);
|
|
||||||
redisClient.on("error", (e) => {
|
|
||||||
console.error("Redis error", e);
|
|
||||||
global.cacheHandlerConfig = null;
|
|
||||||
global.cacheHandlerConfigPromise = null;
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to create Redis client:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (redisClient) {
|
|
||||||
try {
|
|
||||||
console.info("Connecting Redis client...");
|
|
||||||
await redisClient.connect();
|
|
||||||
console.info("Redis client connected.");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to connect Redis client:", error);
|
|
||||||
await redisClient
|
|
||||||
.disconnect()
|
|
||||||
.catch(() => console.error("Failed to quit the Redis client after failing to connect."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const lruCache = createLruHandler();
|
|
||||||
|
|
||||||
if (!redisClient?.isReady) {
|
|
||||||
console.error("Failed to initialize caching layer.");
|
|
||||||
global.cacheHandlerConfigPromise = null;
|
|
||||||
global.cacheHandlerConfig = { handlers: [lruCache] };
|
|
||||||
return global.cacheHandlerConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
const redisCacheHandler = createRedisHandler({
|
|
||||||
client: redisClient,
|
|
||||||
keyPrefix: "nextjs:",
|
|
||||||
});
|
|
||||||
|
|
||||||
global.cacheHandlerConfigPromise = null;
|
|
||||||
|
|
||||||
global.cacheHandlerConfig = {
|
|
||||||
handlers: [redisCacheHandler],
|
|
||||||
};
|
|
||||||
|
|
||||||
return global.cacheHandlerConfig;
|
|
||||||
})();
|
|
||||||
|
|
||||||
return global.cacheHandlerConfigPromise;
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = new Next15CacheHandler();
|
|
||||||
76
apps/web/cache-handler.mjs
Normal file
76
apps/web/cache-handler.mjs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import { Next15CacheHandler } from "@fortedigital/nextjs-cache-handler/next-15-cache-handler";
|
||||||
|
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
|
||||||
|
import { CacheHandler } from "@neshca/cache-handler";
|
||||||
|
import createLruHandler from "@neshca/cache-handler/local-lru";
|
||||||
|
import { createClient } from "redis";
|
||||||
|
|
||||||
|
// Function to create a timeout promise
|
||||||
|
const createTimeoutPromise = (ms, rejectReason) => {
|
||||||
|
return new Promise((_, reject) => setTimeout(() => reject(new Error(rejectReason)), ms));
|
||||||
|
};
|
||||||
|
|
||||||
|
CacheHandler.onCreation(async () => {
|
||||||
|
let client;
|
||||||
|
|
||||||
|
if (process.env.REDIS_URL) {
|
||||||
|
try {
|
||||||
|
// Create a Redis client.
|
||||||
|
client = createClient({
|
||||||
|
url: process.env.REDIS_URL,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Redis won't work without error handling.
|
||||||
|
client.on("error", () => {});
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to create Redis client:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client) {
|
||||||
|
try {
|
||||||
|
// Wait for the client to connect with a timeout of 5000ms.
|
||||||
|
const connectPromise = client.connect();
|
||||||
|
const timeoutPromise = createTimeoutPromise(5000, "Redis connection timed out"); // 5000ms timeout
|
||||||
|
await Promise.race([connectPromise, timeoutPromise]);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to connect Redis client:", error);
|
||||||
|
|
||||||
|
console.warn("Disconnecting the Redis client...");
|
||||||
|
// Try to disconnect the client to stop it from reconnecting.
|
||||||
|
client
|
||||||
|
.disconnect()
|
||||||
|
.then(() => {
|
||||||
|
console.info("Redis client disconnected.");
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.warn("Failed to quit the Redis client after failing to connect.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import("@neshca/cache-handler").Handler | null} */
|
||||||
|
let handler;
|
||||||
|
|
||||||
|
if (client?.isReady) {
|
||||||
|
const redisHandlerOptions = {
|
||||||
|
client,
|
||||||
|
keyPrefix: "fb:",
|
||||||
|
timeoutMs: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create the `redis-stack` Handler if the client is available and connected.
|
||||||
|
handler = await createRedisHandler(redisHandlerOptions);
|
||||||
|
} else {
|
||||||
|
// Fallback to LRU handler if Redis client is not available.
|
||||||
|
// The application will still work, but the cache will be in memory only and not shared.
|
||||||
|
handler = createLruHandler();
|
||||||
|
console.log("Using LRU handler for caching.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
handlers: [handler],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const cacheHandler = new Next15CacheHandler();
|
||||||
|
export default cacheHandler;
|
||||||
@@ -16,7 +16,7 @@ const getHostname = (url) => {
|
|||||||
|
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
assetPrefix: process.env.ASSET_PREFIX_URL || undefined,
|
assetPrefix: process.env.ASSET_PREFIX_URL || undefined,
|
||||||
cacheHandler: require.resolve("./cache-handler.js"),
|
cacheHandler: require.resolve("./cache-handler.mjs"),
|
||||||
cacheMaxMemorySize: 0, // disable default in-memory caching
|
cacheMaxMemorySize: 0, // disable default in-memory caching
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
poweredByHeader: false,
|
poweredByHeader: false,
|
||||||
|
|||||||
Reference in New Issue
Block a user