@@ -40,28 +40,56 @@ export function createIssueTracker(
4040
4141 const tracker : IssueTracker = {
4242 async list ( orgId : string , filter ?: IssueFilter ) : Promise < Issue [ ] > {
43- // If projectId is specified, get remotes for that project; otherwise we'd need all projects
44- // For simplicity, if no projectId, we still need remotes — caller should provide via filter
4543 const projectId = filter ?. projectId ?? ''
4644 const remotes = getRemotes ( orgId , projectId )
4745 const filteredRemotes = filter ?. remote ? remotes . filter ( ( r ) => r . name === filter . remote ) : remotes
4846
4947 let allIssues : Issue [ ] = [ ]
48+ const staleRemotes : Array < { remote : ( typeof filteredRemotes ) [ 0 ] ; pid : string } > = [ ]
5049
5150 for ( const remote of filteredRemotes ) {
5251 const pid = projectId || remote . projectId || remote . name
53- try {
54- const provider = makeProvider ( remote , orgId , pid )
55- const issues = await provider . list ( repoPath ( remote ) , filter )
56- allIssues . push ( ...issues )
57- cache . setCached ( orgId , pid , issues )
58- } catch {
59- // Provider unreachable — serve from cache
52+ // Serve from cache immediately if fresh enough
53+ if ( ! cache . isStale ( orgId , pid ) ) {
6054 const cached = cache . getCached ( orgId , pid )
61- if ( cached ) allIssues . push ( ...cached )
55+ if ( cached ) {
56+ allIssues . push ( ...cached )
57+ continue
58+ }
59+ }
60+ // Cache is stale or missing — try to serve stale data and revalidate in background
61+ const cached = cache . getCached ( orgId , pid )
62+ if ( cached ) {
63+ allIssues . push ( ...cached )
64+ staleRemotes . push ( { remote, pid } )
65+ } else {
66+ // No cache at all — must fetch synchronously
67+ try {
68+ const provider = makeProvider ( remote , orgId , pid )
69+ const issues = await provider . list ( repoPath ( remote ) , filter )
70+ allIssues . push ( ...issues )
71+ cache . setCached ( orgId , pid , issues )
72+ } catch {
73+ // Nothing to serve
74+ }
6275 }
6376 }
6477
78+ // Background revalidation for stale remotes
79+ if ( staleRemotes . length > 0 ) {
80+ void ( async ( ) => {
81+ for ( const { remote, pid } of staleRemotes ) {
82+ try {
83+ const provider = makeProvider ( remote , orgId , pid )
84+ const issues = await provider . list ( repoPath ( remote ) , filter )
85+ cache . setCached ( orgId , pid , issues )
86+ } catch {
87+ // Keep stale cache
88+ }
89+ }
90+ } ) ( )
91+ }
92+
6593 // Apply local filters that providers might not support
6694 if ( filter ?. q ) {
6795 const q = filter . q . toLowerCase ( )
0 commit comments