perf(main): refresh message feed cache in background
This commit is contained in:
parent
6bb8d87bc7
commit
9c29b0f8f1
2 changed files with 61 additions and 4 deletions
|
|
@ -449,6 +449,14 @@ export class TeamMessageFeedService {
|
|||
messages: cached.messages,
|
||||
};
|
||||
}
|
||||
if (cached && !cacheDirty && cacheExpired) {
|
||||
this.refreshCleanExpiredCacheInBackground(teamName, cached, now);
|
||||
return {
|
||||
teamName,
|
||||
feedRevision: cached.feedRevision,
|
||||
messages: cached.messages,
|
||||
};
|
||||
}
|
||||
|
||||
const existingRequest = this.inFlightByTeam.get(teamName);
|
||||
const generationAtStart = this.getGeneration(teamName);
|
||||
|
|
@ -479,6 +487,43 @@ export class TeamMessageFeedService {
|
|||
return this.generationByTeam.get(teamName) ?? 0;
|
||||
}
|
||||
|
||||
private refreshCleanExpiredCacheInBackground(
|
||||
teamName: string,
|
||||
cached: TeamMessageFeedCacheEntry,
|
||||
now: number
|
||||
): void {
|
||||
const generationAtStart = this.getGeneration(teamName);
|
||||
const existingRequest = this.inFlightByTeam.get(teamName);
|
||||
if (existingRequest?.generationAtStart === generationAtStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
const request = this.buildFeed(teamName, cached, now, false, true, generationAtStart).catch(
|
||||
(error) => {
|
||||
logger.debug(
|
||||
`[${teamName}] background message feed refresh failed: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`
|
||||
);
|
||||
return {
|
||||
teamName,
|
||||
feedRevision: cached.feedRevision,
|
||||
messages: cached.messages,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const trackedRequest = request.finally(() => {
|
||||
if (this.inFlightByTeam.get(teamName)?.promise === trackedRequest) {
|
||||
this.inFlightByTeam.delete(teamName);
|
||||
}
|
||||
});
|
||||
this.inFlightByTeam.set(teamName, {
|
||||
promise: trackedRequest,
|
||||
generationAtStart,
|
||||
});
|
||||
}
|
||||
|
||||
private async buildFeed(
|
||||
teamName: string,
|
||||
cached: TeamMessageFeedCacheEntry | undefined,
|
||||
|
|
|
|||
|
|
@ -167,9 +167,12 @@ Messages:
|
|||
]);
|
||||
});
|
||||
|
||||
it('refreshes the durable feed after cache expiry even when the dirty signal was missed', async () => {
|
||||
let inboxMessages: InboxMessage[] = [makeMessage()];
|
||||
const getInboxMessages = vi.fn(async () => inboxMessages);
|
||||
it('returns clean expired cache immediately and refreshes durable feed in the background', async () => {
|
||||
const refreshRequest = createDeferred<InboxMessage[]>();
|
||||
const getInboxMessages = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce([makeMessage()])
|
||||
.mockImplementationOnce(() => refreshRequest.promise);
|
||||
const service = new TeamMessageFeedService({
|
||||
getConfig: vi.fn(async () => config),
|
||||
getInboxMessages,
|
||||
|
|
@ -179,7 +182,7 @@ Messages:
|
|||
|
||||
await service.getFeed('signal-ops-4');
|
||||
|
||||
inboxMessages = [
|
||||
const refreshedMessages = [
|
||||
makeMessage({
|
||||
from: 'jack',
|
||||
to: 'user',
|
||||
|
|
@ -192,6 +195,15 @@ Messages:
|
|||
|
||||
vi.setSystemTime(new Date('2026-04-19T18:46:46.500Z'));
|
||||
|
||||
const stale = await service.getFeed('signal-ops-4');
|
||||
expect(getInboxMessages).toHaveBeenCalledTimes(2);
|
||||
expect(stale.messages).toHaveLength(1);
|
||||
|
||||
refreshRequest.resolve(refreshedMessages);
|
||||
await refreshRequest.promise;
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
|
||||
const refreshed = await service.getFeed('signal-ops-4');
|
||||
expect(getInboxMessages).toHaveBeenCalledTimes(2);
|
||||
expect(
|
||||
|
|
|
|||
Loading…
Reference in a new issue