perf: reuse team summary for comment notification init

This commit is contained in:
777genius 2026-05-29 15:43:24 +03:00
parent e1e5b68e8a
commit b4b9175287
2 changed files with 117 additions and 9 deletions

View file

@ -218,6 +218,12 @@ interface EligibleTaskCommentNotification {
summary: string;
}
interface TaskCommentNotificationTeamContext {
deletedAt?: string;
leadName?: string;
leadSessionId?: string;
}
interface TaskChangeLogSourceSnapshot {
projectFingerprint: string | null;
logSourceGeneration: string | null;
@ -2441,6 +2447,11 @@ export class TeamDataService {
await this.processTaskCommentNotifications(team.teamName, undefined, {
seedHistoricalIfJournalMissing: true,
recoverPending: true,
teamContext: {
deletedAt: team.deletedAt,
leadName: team.leadName,
leadSessionId: team.leadSessionId,
},
});
} catch (error) {
logger.warn(
@ -2722,20 +2733,28 @@ export class TeamDataService {
options?: {
seedHistoricalIfJournalMissing?: boolean;
recoverPending?: boolean;
teamContext?: TaskCommentNotificationTeamContext;
}
): Promise<void> {
const seedHistoricalIfJournalMissing = options?.seedHistoricalIfJournalMissing === true;
const recoverPending = options?.recoverPending === true;
let config: TeamConfig | null = null;
try {
config = await readConfigForUiSnapshot(this.configReader, teamName);
} catch {
return;
}
if (!config || config.deletedAt) return;
const teamContext = options?.teamContext;
if (teamContext?.deletedAt) return;
const leadName = this.resolveLeadNameFromConfig(config);
const leadSessionId = config.leadSessionId;
let leadName = teamContext?.leadName?.trim() ?? '';
let leadSessionId = teamContext?.leadSessionId;
if (!leadName) {
let config: TeamConfig | null = null;
try {
config = await readConfigForUiSnapshot(this.configReader, teamName);
} catch {
return;
}
if (!config || config.deletedAt) return;
leadName = this.resolveLeadNameFromConfig(config);
leadSessionId = config.leadSessionId;
}
if (!leadName.trim()) return;
const journalExists = await this.taskCommentNotificationJournal.exists(teamName);

View file

@ -2520,6 +2520,95 @@ describe('TeamDataService', () => {
}
});
it('uses startup team summary lead fields without rereading config for comment notification baselines', async () => {
const previous = process.env[TASK_COMMENT_FORWARDING_ENV];
process.env[TASK_COMMENT_FORWARDING_ENV] = 'on';
const journalEntries: Array<Record<string, unknown>> = [];
const inboxWriter = { sendMessage: vi.fn() };
const getConfig = vi.fn(async () => {
throw new Error('unexpected config read');
});
const journal = {
exists: vi.fn(async () => false),
ensureFile: vi.fn(async () => undefined),
withEntries: vi.fn(
async (_teamName: string, fn: (entries: unknown[]) => Promise<{ result: unknown }>) => {
const outcome = await fn(journalEntries);
return outcome.result;
}
),
};
try {
const service = new TeamDataService(
{
listTeams: vi.fn(async () => [
{
teamName: 'my-team',
displayName: 'My team',
description: '',
memberCount: 1,
taskCount: 1,
lastActivity: null,
leadName: 'team-lead',
leadSessionId: 'lead-1',
},
]),
getConfig,
} as never,
{
getTasks: vi.fn(async () => [
{
id: 'task-1',
displayId: 'abcd1234',
subject: 'Investigate',
status: 'pending',
owner: 'alice',
comments: [
{
id: 'comment-1',
author: 'alice',
text: 'Found the root cause.',
createdAt: '2026-03-14T10:00:00.000Z',
type: 'regular',
},
],
},
]),
} as never,
{
listInboxNames: vi.fn(async () => []),
getMessages: vi.fn(async () => []),
getMessagesFor: vi.fn(async () => []),
} as never,
inboxWriter as never,
{} as never,
{} as never,
{} as never,
{} as never,
{} as never,
{} as never,
(() => ({}) as never) as never,
journal as never
);
await service.initializeTaskCommentNotificationState();
expect(getConfig).not.toHaveBeenCalled();
expect(inboxWriter.sendMessage).not.toHaveBeenCalled();
expect(journalEntries).toEqual([
expect.objectContaining({
key: 'task-1:comment-1',
state: 'seeded',
messageId: 'task-comment-forward:my-team:task-1:comment-1',
}),
]);
} finally {
if (previous === undefined) delete process.env[TASK_COMMENT_FORWARDING_ENV];
else process.env[TASK_COMMENT_FORWARDING_ENV] = previous;
}
});
it('forwards a new eligible task comment to the lead exactly once in live mode', async () => {
const previous = process.env[TASK_COMMENT_FORWARDING_ENV];
process.env[TASK_COMMENT_FORWARDING_ENV] = 'on';