@@ -19,8 +19,29 @@ import express from 'express';
1919import { randomUUID } from 'node:crypto' ;
2020import { InputError , NotFoundError } from '@backstage/errors' ;
2121
22+ import type { Module } from '@red-hat-developer-hub/backstage-plugin-x2a-common' ;
23+
2224import type { RouterDeps } from './types' ;
2325import { getUserRef , reconcileJobStatus } from './common' ;
26+ import { calculateModuleStatus } from '../services/X2ADatabaseService/status' ;
27+
28+ /**
29+ * Reconcile any pending/running phase jobs on a module against K8s state.
30+ * Mutates the module in-place and returns it.
31+ */
32+ async function reconcileModuleJobs (
33+ module : Module ,
34+ deps : Pick < RouterDeps , 'kubeService' | 'x2aDatabase' | 'logger' > ,
35+ ) : Promise < Module > {
36+ const phases = [ 'analyze' , 'migrate' , 'publish' ] as const ;
37+ for ( const phase of phases ) {
38+ const job = module [ phase ] ;
39+ if ( job && [ 'pending' , 'running' ] . includes ( job . status ) ) {
40+ module [ phase ] = await reconcileJobStatus ( job , deps ) ;
41+ }
42+ }
43+ return module ;
44+ }
2445
2546export function registerModuleRoutes (
2647 router : express . Router ,
@@ -49,6 +70,24 @@ export function registerModuleRoutes(
4970 // List modules
5071 const modules = await x2aDatabase . listModules ( { projectId } ) ;
5172
73+ // Reconcile any pending/running jobs against K8s
74+ await Promise . all (
75+ modules . map ( m =>
76+ reconcileModuleJobs ( m , { kubeService, x2aDatabase, logger } ) ,
77+ ) ,
78+ ) ;
79+
80+ // Recalculate status for each module after reconciliation
81+ for ( const m of modules ) {
82+ const { status, errorDetails } = calculateModuleStatus ( {
83+ analyze : m . analyze ,
84+ migrate : m . migrate ,
85+ publish : m . publish ,
86+ } ) ;
87+ m . status = status ;
88+ m . errorDetails = errorDetails ;
89+ }
90+
5291 res . json ( modules ) ;
5392 } ) ;
5493
@@ -85,6 +124,18 @@ export function registerModuleRoutes(
85124 ) ;
86125 }
87126
127+ // Reconcile any pending/running jobs against K8s
128+ await reconcileModuleJobs ( module , { kubeService, x2aDatabase, logger } ) ;
129+
130+ // Recalculate status after reconciliation may have updated phase jobs
131+ const { status, errorDetails } = calculateModuleStatus ( {
132+ analyze : module . analyze ,
133+ migrate : module . migrate ,
134+ publish : module . publish ,
135+ } ) ;
136+ module . status = status ;
137+ module . errorDetails = errorDetails ;
138+
88139 res . json ( module ) ;
89140 } ) ;
90141
@@ -293,7 +344,10 @@ export function registerModuleRoutes(
293344 } ) ;
294345
295346 // Update job with k8s job name
296- await x2aDatabase . updateJob ( { id : job . id , k8sJobName } ) ;
347+ await x2aDatabase . updateJob ( {
348+ id : job . id ,
349+ k8sJobName,
350+ } ) ;
297351
298352 logger . info (
299353 `${ phase } job created: jobId=${ job . id } , moduleId=${ moduleId } , k8sJobName=${ k8sJobName } ` ,
0 commit comments