mirror of
https://github.com/FJurmanovic/sugarr.git
synced 2026-11-11 07:41:08 +00:00
Wire up cron scheduling and the app entrypoint
This commit is contained in:
26
src/app/cron.ts
Normal file
26
src/app/cron.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import cron from 'node-cron';
|
||||
import type { Logger } from '../core/logging/logger';
|
||||
import type { AppConfig } from './config/AppConfig';
|
||||
import type { RecommendationPipeline } from './pipelines/RecommendationPipeline';
|
||||
|
||||
export function scheduleCron(config: AppConfig, pipeline: RecommendationPipeline, logger: Logger): void {
|
||||
if (!config.CRON_ENABLED) return;
|
||||
|
||||
cron.schedule(config.CRON_SCHEDULE, async () => {
|
||||
logger.info('Cron: running recommendation pipeline');
|
||||
try {
|
||||
const recommendations = await pipeline.runAsync({
|
||||
count: config.RECOMMEND_COUNT,
|
||||
useLlm: config.LLM_ENABLED,
|
||||
});
|
||||
if (config.RADARR_ENABLED) {
|
||||
await pipeline.autoRequest(recommendations);
|
||||
}
|
||||
logger.info({ count: recommendations.length }, 'Cron: pipeline finished');
|
||||
} catch (err) {
|
||||
logger.error({ err }, 'Cron: pipeline failed');
|
||||
}
|
||||
});
|
||||
|
||||
logger.info({ schedule: config.CRON_SCHEDULE }, 'Cron scheduled');
|
||||
}
|
||||
86
src/app/index.ts
Normal file
86
src/app/index.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'dotenv/config';
|
||||
import { loadAppConfig } from './config/AppConfig';
|
||||
import { createLogger } from '../core/logging/logger';
|
||||
import { LangfuseTracer } from '../core/langfuse/LangfuseTracer';
|
||||
import { LangfusePromptGateway } from '../core/langfuse/LangfusePromptGateway';
|
||||
import { PromptService } from '../core/langfuse/PromptService';
|
||||
import { LlmClient } from '../core/llm/LlmClient';
|
||||
import { buildServer } from '../core/server/buildServer';
|
||||
import { JellyfinClient } from './clients/jellyfin/JellyfinClient';
|
||||
import { TmdbClient } from './clients/tmdb/TmdbClient';
|
||||
import { RadarrClient } from './clients/radarr/RadarrClient';
|
||||
import { MovieRecommenderTool } from './tools/MovieRecommenderTool';
|
||||
import { MovieSearchTool } from './tools/MovieSearchTool';
|
||||
import { RecommendationPipeline } from './pipelines/RecommendationPipeline';
|
||||
import { HealthController } from './controllers/HealthController';
|
||||
import { RecommendationsController } from './controllers/RecommendationsController';
|
||||
import { RequestController } from './controllers/RequestController';
|
||||
import { WebhookController } from './controllers/WebhookController';
|
||||
import { scheduleCron } from './cron';
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const config = loadAppConfig();
|
||||
const logger = createLogger('sugarr');
|
||||
|
||||
const langfuseOpts = {
|
||||
publicKey: config.LANGFUSE_PUBLIC_KEY,
|
||||
secretKey: config.LANGFUSE_SECRET_KEY,
|
||||
baseUrl: config.LANGFUSE_BASE_URL,
|
||||
};
|
||||
const tracer = new LangfuseTracer(langfuseOpts);
|
||||
const promptGateway = new LangfusePromptGateway(langfuseOpts);
|
||||
const promptService = new PromptService(promptGateway, config.LANGFUSE_PROMPT_CACHE_ENABLED);
|
||||
const llmClient = new LlmClient({ baseUrl: config.LLM_BASE_URL, apiKey: config.LLM_API_KEY });
|
||||
|
||||
const jellyfin = new JellyfinClient(config.JELLYFIN_URL, config.JELLYFIN_API_KEY, config.JELLYFIN_USER_ID);
|
||||
const tmdb = new TmdbClient(config.TMDB_API_KEY);
|
||||
const radarr = config.RADARR_ENABLED
|
||||
? new RadarrClient(config.RADARR_URL, config.RADARR_API_KEY, config.RADARR_QUALITY_PROFILE_ID, config.RADARR_ROOT_FOLDER)
|
||||
: undefined;
|
||||
|
||||
const recommenderTool = new MovieRecommenderTool(promptService, llmClient);
|
||||
const searchTool = new MovieSearchTool(promptService, llmClient);
|
||||
|
||||
const pipeline = new RecommendationPipeline(tracer, logger, {
|
||||
jellyfin,
|
||||
tmdb,
|
||||
radarr,
|
||||
tool: recommenderTool,
|
||||
searchTool,
|
||||
minRatedMovies: config.MIN_RATED_MOVIES,
|
||||
maxRetry: config.RECOMMEND_MAX_RETRY,
|
||||
});
|
||||
|
||||
logger.info(
|
||||
{
|
||||
jellyfin: config.JELLYFIN_URL,
|
||||
llmEnabled: config.LLM_ENABLED,
|
||||
radarrEnabled: config.RADARR_ENABLED,
|
||||
cronEnabled: config.CRON_ENABLED,
|
||||
apiEnabled: config.API_ENABLED,
|
||||
},
|
||||
'sugarr starting'
|
||||
);
|
||||
|
||||
scheduleCron(config, pipeline, logger);
|
||||
|
||||
if (config.API_ENABLED) {
|
||||
const app = buildServer({
|
||||
secretKey: config.SECRET_KEY,
|
||||
controllers: [
|
||||
new HealthController(config),
|
||||
new RecommendationsController(config, pipeline),
|
||||
new RequestController(config, radarr),
|
||||
new WebhookController(promptService),
|
||||
],
|
||||
});
|
||||
await app.listen({ port: config.API_PORT, host: '0.0.0.0' });
|
||||
logger.info({ port: config.API_PORT }, 'HTTP API listening');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user