- Added AccessControl to ComboHandler for role-based access management. - Implemented gas estimation for plan execution and improved gas limit checks. - Updated execution and preparation methods to enforce step count limits and role restrictions. - Enhanced error handling in orchestrator API endpoints with AppError for better validation feedback. - Integrated request timeout middleware for improved request management. - Updated Swagger documentation to reflect new API structure and parameters.
108 lines
2.3 KiB
TypeScript
108 lines
2.3 KiB
TypeScript
import Redis from "ioredis";
|
|
import express from "express";
|
|
|
|
/**
|
|
* Redis caching service
|
|
*/
|
|
let redis: Redis | null = null;
|
|
|
|
/**
|
|
* Initialize Redis connection
|
|
*/
|
|
export function initRedis(url?: string): Redis {
|
|
if (!redis) {
|
|
redis = new Redis(url || process.env.REDIS_URL || "redis://localhost:6379", {
|
|
maxRetriesPerRequest: 3,
|
|
retryStrategy: (times) => {
|
|
const delay = Math.min(times * 50, 2000);
|
|
return delay;
|
|
},
|
|
});
|
|
|
|
redis.on("error", (err) => {
|
|
console.error("Redis connection error:", err);
|
|
});
|
|
|
|
redis.on("connect", () => {
|
|
console.log("✅ Redis connected");
|
|
});
|
|
}
|
|
|
|
return redis;
|
|
}
|
|
|
|
/**
|
|
* Get Redis client
|
|
*/
|
|
export function getRedis(): Redis | null {
|
|
if (!redis && process.env.REDIS_URL) {
|
|
initRedis();
|
|
}
|
|
return redis;
|
|
}
|
|
|
|
/**
|
|
* Cache wrapper with TTL
|
|
*/
|
|
export async function cacheGet<T>(key: string): Promise<T | null> {
|
|
const client = getRedis();
|
|
if (!client) return null;
|
|
|
|
try {
|
|
const value = await client.get(key);
|
|
return value ? JSON.parse(value) : null;
|
|
} catch (error) {
|
|
console.error("Cache get error:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function cacheSet<T>(key: string, value: T, ttlSeconds = 3600): Promise<void> {
|
|
const client = getRedis();
|
|
if (!client) return;
|
|
|
|
try {
|
|
await client.setex(key, ttlSeconds, JSON.stringify(value));
|
|
} catch (error) {
|
|
console.error("Cache set error:", error);
|
|
}
|
|
}
|
|
|
|
export async function cacheDelete(key: string): Promise<void> {
|
|
const client = getRedis();
|
|
if (!client) return;
|
|
|
|
try {
|
|
await client.del(key);
|
|
} catch (error) {
|
|
console.error("Cache delete error:", error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cache middleware for Express routes
|
|
*/
|
|
export function cacheMiddleware(ttlSeconds = 300) {
|
|
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
|
if (req.method !== "GET") {
|
|
return next();
|
|
}
|
|
|
|
const cacheKey = `cache:${req.path}:${JSON.stringify(req.query)}`;
|
|
const cached = await cacheGet(cacheKey);
|
|
|
|
if (cached) {
|
|
return res.json(cached);
|
|
}
|
|
|
|
const originalSend = res.json;
|
|
res.json = function (body: any) {
|
|
cacheSet(cacheKey, body, ttlSeconds).catch(console.error);
|
|
return originalSend.call(this, body);
|
|
};
|
|
|
|
next();
|
|
};
|
|
}
|
|
|