Skip to content

Commit b0472c5

Browse files
committed
fix(webapp): start registry reload interval only after first load
Prevents the startup retry from racing the reload interval: an interval tick firing mid-startup-load would bump the load sequence and discard the startup result, leaving the registry cold until a later reload. Start polling only after the first successful load.
1 parent 1930f26 commit b0472c5

1 file changed

Lines changed: 19 additions & 16 deletions

File tree

apps/webapp/app/utils/reloadingRegistry.server.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ export function createReloadingRegistry<T>(opts: ReloadingRegistryOptions<T>): R
6464
resolveReady = resolve;
6565
});
6666

67+
let interval: ReturnType<typeof setInterval> | undefined;
68+
69+
function startReloadInterval() {
70+
interval = setInterval(() => {
71+
doLoad().catch((err) => {
72+
loadFailures.inc({ name: opts.name });
73+
logger.warn("[ReloadingRegistry] reload failed", {
74+
name: opts.name,
75+
error: err instanceof Error ? err.message : String(err),
76+
});
77+
});
78+
}, opts.intervalMs);
79+
interval.unref(); // never keep the process alive; SIGTERM still clears it
80+
}
81+
6782
async function doLoad() {
6883
const seq = ++loadSeq;
6984
const next = await opts.load();
@@ -74,15 +89,15 @@ export function createReloadingRegistry<T>(opts: ReloadingRegistryOptions<T>): R
7489
loaded = true;
7590
registryLoaded.set({ name: opts.name }, 1);
7691
resolveReady();
92+
// Poll only after the first load lands, so the startup retry can't race it.
93+
if (opts.autoStart !== false) startReloadInterval();
7794
}
7895
}
7996

80-
let interval: ReturnType<typeof setInterval> | undefined;
81-
8297
if (opts.autoStart !== false) {
8398
registryLoaded.set({ name: opts.name }, 0); // visible cold series until first load
8499

85-
const startup = pRetry(() => doLoad(), {
100+
pRetry(() => doLoad(), {
86101
forever: opts.retry?.retries === undefined,
87102
retries: opts.retry?.retries,
88103
minTimeout: 1_000,
@@ -97,24 +112,12 @@ export function createReloadingRegistry<T>(opts: ReloadingRegistryOptions<T>): R
97112
error: error.message,
98113
});
99114
},
100-
});
101-
startup.catch((err) => {
115+
}).catch((err) => {
102116
logger.error("[ReloadingRegistry] startup load gave up", {
103117
name: opts.name,
104118
error: err instanceof Error ? err.message : String(err),
105119
});
106120
});
107-
108-
interval = setInterval(() => {
109-
doLoad().catch((err) => {
110-
loadFailures.inc({ name: opts.name });
111-
logger.warn("[ReloadingRegistry] reload failed", {
112-
name: opts.name,
113-
error: err instanceof Error ? err.message : String(err),
114-
});
115-
});
116-
}, opts.intervalMs);
117-
interval.unref(); // never keep the process alive; SIGTERM still clears it
118121
} else {
119122
resolveReady(); // inert: any direct `await isReady` resolves immediately
120123
}

0 commit comments

Comments
 (0)