@@ -221,20 +221,6 @@ function setupEventForwarding(): void {
221221 console . log ( '[Events] Event forwarding configured for WebUI' ) ;
222222}
223223
224- /**
225- * Start polling for all connected contexts
226- */
227- function startPolling ( ) : void {
228- for ( const contextId of connectedContexts ) {
229- try {
230- pollingCoordinator . startPollingForContext ( contextId ) ;
231- console . log ( `[Polling] Started for context: ${ contextId } ` ) ;
232- } catch ( error ) {
233- console . error ( `[Polling] Failed to start for context ${ contextId } :` , error ) ;
234- }
235- }
236- }
237-
238224/**
239225 * Initialize camera proxies for all connected contexts
240226 */
@@ -391,7 +377,65 @@ async function main(): Promise<void> {
391377 multiContextSpoolmanTracker . initialize ( ) ;
392378 console . log ( '[Init] Spoolman tracker initialized' ) ;
393379
394- // 10. Connect to printers
380+ // 10. Setup event handlers BEFORE connecting to printers
381+ // This ensures handlers are ready when backend-initialized events fire during connection
382+ setupEventForwarding ( ) ;
383+
384+ // 10b. Setup post-connection hook for logging
385+ connectionManager . on ( 'connected' , ( printerDetails ) => {
386+ console . log ( `[Events] Printer connected: ${ printerDetails . Name } ` ) ;
387+ // Polling and monitors are initialized by backend-initialized handler
388+ } ) ;
389+ console . log ( '[Events] Post-connection hook configured' ) ;
390+
391+ // 10c. Setup backend-initialized hook to start polling and create monitors
392+ // This is critical for Spoolman deduction and print state monitoring
393+ // IMPORTANT: This handles both startup connections AND dynamic connections (API reconnect/discovery)
394+ connectionManager . on ( 'backend-initialized' , ( event : unknown ) => {
395+ const backendEvent = event as { contextId : string ; modelType : string } ;
396+ const contextId = backendEvent . contextId ;
397+
398+ console . log ( `[Events] Backend initialized for context ${ contextId } , starting services...` ) ;
399+
400+ try {
401+ // STEP 1: Start polling FIRST (this creates the pollingService reference)
402+ pollingCoordinator . startPollingForContext ( contextId ) ;
403+ console . log ( `[Polling] Started for context: ${ contextId } ` ) ;
404+
405+ // STEP 2: Get context and polling service (now available after step 1)
406+ const context = contextManager . getContext ( contextId ) ;
407+ const pollingService = context ?. pollingService ;
408+
409+ if ( ! pollingService ) {
410+ console . error ( '[Events] Missing polling service for context initialization' ) ;
411+ return ;
412+ }
413+
414+ // STEP 3: Create PrintStateMonitor for this context
415+ const printStateMonitor = getMultiContextPrintStateMonitor ( ) ;
416+ printStateMonitor . createMonitorForContext ( contextId , pollingService ) ;
417+ const stateMonitor = printStateMonitor . getMonitor ( contextId ) ;
418+
419+ if ( ! stateMonitor ) {
420+ console . error ( '[Events] Failed to create print state monitor' ) ;
421+ return ;
422+ }
423+
424+ console . log ( `[Events] Created PrintStateMonitor for context ${ contextId } ` ) ;
425+
426+ // STEP 4: Create SpoolmanTracker for this context (depends on PrintStateMonitor)
427+ const spoolmanTracker = getMultiContextSpoolmanTracker ( ) ;
428+ spoolmanTracker . createTrackerForContext ( contextId , stateMonitor ) ;
429+
430+ console . log ( `[Events] Created SpoolmanTracker for context ${ contextId } ` ) ;
431+ console . log ( `[Events] All services initialized for context ${ contextId } ` ) ;
432+ } catch ( error ) {
433+ console . error ( `[Events] Failed to initialize services for context ${ contextId } :` , error ) ;
434+ }
435+ } ) ;
436+ console . log ( '[Events] Backend-initialized hook configured' ) ;
437+
438+ // 11. Connect to printers (handlers are now ready to receive backend-initialized events)
395439 console . log ( '[Init] Connecting to printers...' ) ;
396440 connectedContexts = await connectPrinters ( config ) ;
397441
@@ -409,35 +453,13 @@ async function main(): Promise<void> {
409453 }
410454 }
411455
412- // 11 . Start WebUI server
456+ // 12 . Start WebUI server
413457 await startWebUI ( ) ;
414458
415- // 12. Setup event forwarding BEFORE starting polling
416- // This ensures listeners are ready when polling data starts flowing
417- setupEventForwarding ( ) ;
418-
419- // 12b. Setup post-connection hook for dynamic printer connections
420- // This handles printers connected after startup (via API reconnect/discovery)
421- connectionManager . on ( 'connected' , ( printerDetails ) => {
422- const activeContextId = contextManager . getActiveContextId ( ) ;
423- if ( activeContextId ) {
424- console . log ( `[Events] Printer connected: ${ printerDetails . Name } , starting services...` ) ;
425-
426- // Start polling for the new context
427- try {
428- pollingCoordinator . startPollingForContext ( activeContextId ) ;
429- console . log ( `[Polling] Started for context: ${ activeContextId } ` ) ;
430- } catch ( error ) {
431- console . error ( `[Polling] Failed to start for context ${ activeContextId } :` , error ) ;
432- }
433- }
434- } ) ;
435- console . log ( '[Events] Post-connection hook configured' ) ;
436-
437- // 13. Start polling for connected printers
459+ // 13. Note: Polling and monitors are initialized by backend-initialized handler
460+ // This handler fires for both startup connections AND dynamic connections
438461 if ( connectedContexts . length > 0 ) {
439- startPolling ( ) ;
440- console . log ( `[Init] Polling started for ${ connectedContexts . length } printer(s)` ) ;
462+ console . log ( `[Init] Services initialized for ${ connectedContexts . length } printer(s) via backend-initialized handler` ) ;
441463 }
442464
443465 // 14. Initialize camera proxies
0 commit comments