fixed cache keys

This commit is contained in:
Boki 2025-06-22 20:34:35 -04:00
parent db3aa9c330
commit 19dfda2392
13 changed files with 286 additions and 221 deletions

View file

@ -61,6 +61,11 @@ const appConfigSchema = z.object({
timeout: z.number().optional(),
})
.optional(),
queue: z
.object({
enabled: z.boolean().optional(),
})
.optional(),
});
export type AppConfig = z.infer<typeof appConfigSchema>;
@ -114,13 +119,14 @@ export function createServiceContainer(rawConfig: unknown): AwilixContainer<Serv
logger: asFunction(() => getLogger('app')).singleton(),
};
// Conditionally register cache/dragonfly
// Conditionally register cache/dragonfly instances
if (config.redis?.enabled !== false) {
// Main cache instance
registrations.cache = asFunction(({ redisConfig, logger }) =>
createCache({
redisConfig,
logger,
keyPrefix: 'cache:',
keyPrefix: '', // No prefix at this level, namespaces will handle it
ttl: 3600,
enableMetrics: true,
})
@ -129,13 +135,15 @@ export function createServiceContainer(rawConfig: unknown): AwilixContainer<Serv
registrations.cache = asValue(null);
}
// Proxy manager depends on cache
// Proxy manager creates its own namespaced cache
registrations.proxyManager = asFunction(({ cache, config, logger }) => {
if (!cache) {
logger.warn('Cache is disabled, ProxyManager will have limited functionality');
return null;
}
const manager = new ProxyManager(cache, config.proxy || {}, logger);
const { NamespacedCache } = require('@stock-bot/cache');
const proxyCache = new NamespacedCache(cache, 'proxy');
const manager = new ProxyManager(proxyCache, config.proxy || {}, logger);
return manager;
}).singleton();
@ -188,22 +196,26 @@ export function createServiceContainer(rawConfig: unknown): AwilixContainer<Serv
registrations.questdbClient = asValue(null);
}
// Queue manager - properly instantiated with DI
registrations.queueManager = asFunction(({ redisConfig, logger }) => {
const { QueueManager } = require('@stock-bot/queue');
return new QueueManager({
redis: {
host: redisConfig.host,
port: redisConfig.port,
db: redisConfig.db,
password: redisConfig.password,
username: redisConfig.username,
},
enableScheduledJobs: true,
delayWorkerStart: true, // We'll start workers manually
});
}).singleton();
// Queue manager - conditionally registered with logger injection
if (config.redis?.enabled !== false && config.queue?.enabled !== false) {
registrations.queueManager = asFunction(({ redisConfig, logger }) => {
const { QueueManager } = require('@stock-bot/queue');
return new QueueManager({
redis: {
host: redisConfig.host,
port: redisConfig.port,
db: redisConfig.db,
password: redisConfig.password,
username: redisConfig.username,
},
enableScheduledJobs: true,
delayWorkerStart: true, // We'll start workers manually
}, logger); // Pass logger to QueueManager
}).singleton();
} else {
registrations.queueManager = asValue(null);
}
// Browser automation
registrations.browser = asFunction(({ config, logger }) => {
@ -377,6 +389,9 @@ export function createServiceContainerFromConfig(
headless: true,
timeout: 30000,
} : undefined,
queue: {
enabled: enableQueue && enableCache, // Queue depends on Redis/cache
},
};
return createServiceContainer(containerConfig);

View file

@ -6,6 +6,7 @@ import {
type HandlerConfigWithSchedule,
} from '@stock-bot/types';
import { fetch } from '@stock-bot/utils';
import { createNamespacedCache } from '@stock-bot/cache';
import type { IServiceContainer } from '../types/service-container';
import type { ExecutionContext, IHandler } from '../types/types';
@ -126,6 +127,14 @@ export abstract class BaseHandler implements IHandler {
return this.mongodb.collection(name);
}
/**
* Create a sub-namespaced cache for specific operations
* Example: handler 'webshare' creates namespace 'webshare:api' -> keys will be 'cache:webshare:api:*'
*/
protected createNamespacedCache(subNamespace: string) {
return createNamespacedCache(this.cache, `${this.handlerName}:${subNamespace}`);
}
/**
* Set cache with handler-prefixed key
*/
@ -133,7 +142,7 @@ export abstract class BaseHandler implements IHandler {
if (!this.cache) {
return;
}
return this.cache.set(`${this.handlerName}:${key}`, value, ttl);
return this.cache.set(`cache:${this.handlerName}:${key}`, value, ttl);
}
/**
@ -143,7 +152,7 @@ export abstract class BaseHandler implements IHandler {
if (!this.cache) {
return null;
}
return this.cache.get(`${this.handlerName}:${key}`);
return this.cache.get(`cache:${this.handlerName}:${key}`);
}
/**
@ -153,7 +162,7 @@ export abstract class BaseHandler implements IHandler {
if (!this.cache) {
return;
}
return this.cache.del(`${this.handlerName}:${key}`);
return this.cache.del(`cache:${this.handlerName}:${key}`);
}
/**