@@ -10,6 +10,12 @@ import { RebalancingService } from './monitoring/rebalancer.js'
1010import { AutoRebalancerService } from './services/autoRebalancer.js'
1111import { logger } from './utils/logger.js'
1212import { databaseService } from './services/databaseService.js'
13+ import { isRedisAvailable , logQueueStartup } from './queue/connection.js'
14+ import { startQueueScheduler } from './queue/scheduler.js'
15+ import { startPortfolioCheckWorker , stopPortfolioCheckWorker } from './queue/workers/portfolioCheckWorker.js'
16+ import { startRebalanceWorker , stopRebalanceWorker } from './queue/workers/rebalanceWorker.js'
17+ import { startAnalyticsSnapshotWorker , stopAnalyticsSnapshotWorker } from './queue/workers/analyticsSnapshotWorker.js'
18+ import { closeAllQueues } from './queue/queues.js'
1319
1420const app = express ( )
1521const port = process . env . PORT || 3001
@@ -62,6 +68,9 @@ app.use((req, res, next) => {
6268
6369app . use ( globalRateLimiter )
6470
71+ // Create auto-rebalancer instance
72+ const autoRebalancer = new AutoRebalancerService ( )
73+
6574// Health check endpoint
6675app . get ( '/health' , ( req , res ) => {
6776 res . json ( {
@@ -139,14 +148,12 @@ app.get('/', (req, res) => {
139148 health : '/health' ,
140149 corsTest : '/test/cors' ,
141150 coinGeckoTest : '/test/coingecko' ,
142- autoRebalancerStatus : '/api/auto-rebalancer/status'
151+ autoRebalancerStatus : '/api/auto-rebalancer/status' ,
152+ queueHealth : '/api/queue/health'
143153 }
144154 } )
145155} )
146156
147- // Create auto-rebalancer instance
148- const autoRebalancer = new AutoRebalancerService ( )
149-
150157// Mount API routes
151158app . use ( '/api' , portfolioRouter )
152159app . use ( '/' , portfolioRouter )
@@ -161,7 +168,8 @@ app.use((req, res) => {
161168 availableEndpoints : {
162169 health : '/health' ,
163170 api : '/api/*' ,
164- autoRebalancer : '/api/auto-rebalancer/*'
171+ autoRebalancer : '/api/auto-rebalancer/*' ,
172+ queueHealth : '/api/queue/health'
165173 }
166174 } )
167175} )
@@ -194,30 +202,49 @@ wss.on('connection', (ws) => {
194202 } )
195203} )
196204
197- // Start existing rebalancing service
205+ // Start existing rebalancing service (now queue-backed, no cron)
198206try {
199207 const rebalancingService = new RebalancingService ( wss )
200208 rebalancingService . start ( )
201- console . log ( '[LEGACY-REBALANCER] Legacy rebalancing service started' )
209+ console . log ( '[REBALANCING-SERVICE] Monitoring service started (queue-backed) ' )
202210} catch ( error ) {
203- console . error ( 'Failed to start legacy rebalancing service:' , error )
211+ console . error ( 'Failed to start rebalancing service:' , error )
204212}
205213
206214// Start server
207- server . listen ( port , ( ) => {
215+ server . listen ( port , async ( ) => {
208216 console . log ( `🚀 Server running on port ${ port } ` )
209217 console . log ( `Environment: ${ process . env . NODE_ENV || 'development' } ` )
210218 console . log ( `CoinGecko API Key: ${ ! ! process . env . COINGECKO_API_KEY ? 'SET' : 'NOT SET' } ` )
211219
212- // Start automatic rebalancing service
220+ // ── BullMQ / Redis setup ────────────────────────────────────────────────
221+ const redisAvailable = await isRedisAvailable ( )
222+ logQueueStartup ( redisAvailable )
223+
224+ if ( redisAvailable ) {
225+ // Start all three workers
226+ startPortfolioCheckWorker ( )
227+ startRebalanceWorker ( )
228+ startAnalyticsSnapshotWorker ( )
229+
230+ // Register repeatable jobs (scheduler)
231+ try {
232+ await startQueueScheduler ( )
233+ console . log ( '[SCHEDULER] ✅ Queue scheduler registered' )
234+ } catch ( err ) {
235+ console . error ( '[SCHEDULER] ❌ Failed to register scheduler:' , err )
236+ }
237+ }
238+
239+ // ── Auto-rebalancer (queue-backed) ──────────────────────────────────────
213240 const shouldStartAutoRebalancer =
214241 process . env . NODE_ENV === 'production' ||
215242 process . env . ENABLE_AUTO_REBALANCER === 'true'
216243
217244 if ( shouldStartAutoRebalancer ) {
218245 try {
219246 console . log ( '[AUTO-REBALANCER] Starting automatic rebalancing service...' )
220- autoRebalancer . start ( )
247+ await autoRebalancer . start ( )
221248 console . log ( '[AUTO-REBALANCER] ✅ Automatic rebalancing service started successfully' )
222249
223250 // Broadcast to WebSocket clients
@@ -243,10 +270,11 @@ server.listen(port, () => {
243270 console . log ( ` CORS Test: http://localhost:${ port } /test/cors` )
244271 console . log ( ` CoinGecko Test: http://localhost:${ port } /test/coingecko` )
245272 console . log ( ` Auto-Rebalancer Status: http://localhost:${ port } /api/auto-rebalancer/status` )
273+ console . log ( ` Queue Health: http://localhost:${ port } /api/queue/health` )
246274} )
247275
248276// Graceful shutdown
249- const gracefulShutdown = ( signal : string ) => {
277+ const gracefulShutdown = async ( signal : string ) => {
250278 console . log ( `\n[SHUTDOWN] ${ signal } received, shutting down gracefully...` )
251279
252280 // Stop auto-rebalancer
@@ -257,6 +285,26 @@ const gracefulShutdown = (signal: string) => {
257285 console . error ( '[SHUTDOWN] Error stopping auto-rebalancer:' , error )
258286 }
259287
288+ // Stop BullMQ workers
289+ try {
290+ await Promise . all ( [
291+ stopPortfolioCheckWorker ( ) ,
292+ stopRebalanceWorker ( ) ,
293+ stopAnalyticsSnapshotWorker ( ) ,
294+ ] )
295+ console . log ( '[SHUTDOWN] BullMQ workers stopped' )
296+ } catch ( error ) {
297+ console . error ( '[SHUTDOWN] Error stopping BullMQ workers:' , error )
298+ }
299+
300+ // Close BullMQ queues
301+ try {
302+ await closeAllQueues ( )
303+ console . log ( '[SHUTDOWN] BullMQ queues closed' )
304+ } catch ( error ) {
305+ console . error ( '[SHUTDOWN] Error closing queues:' , error )
306+ }
307+
260308 // Close database connection
261309 try {
262310 databaseService . close ( )
0 commit comments