perf(main): skip unchanged task resume locks
This commit is contained in:
parent
7ea57cb012
commit
c2ab7a7ff4
2 changed files with 54 additions and 0 deletions
|
|
@ -333,6 +333,10 @@ function writeTaskFile(filePath: string, task: MutableTeamTask): void {
|
|||
export class TeamTaskActivityIntervalService {
|
||||
private readonly resumeMembersCache = new Map<string, ResumeMembersCacheEntry>();
|
||||
|
||||
private getBoardStateLockPath(teamName: string): string {
|
||||
return `${path.join(getTeamsBasePath(), teamName, 'board-state')}.lock`;
|
||||
}
|
||||
|
||||
private mutateTeamTasksWithLock(
|
||||
teamName: string,
|
||||
run: () => ActivityIntervalResult
|
||||
|
|
@ -520,6 +524,18 @@ export class TeamTaskActivityIntervalService {
|
|||
if (memberKeys.size === 0) return { changedTasks: 0 };
|
||||
const memberKey = this.makeMemberSetKey(memberKeys);
|
||||
|
||||
const cachedBeforeLock = this.resumeMembersCache.get(teamName);
|
||||
if (cachedBeforeLock?.memberKey === memberKey) {
|
||||
const beforeLockSignature = this.readTaskDirectorySignature(teamName);
|
||||
if (
|
||||
beforeLockSignature &&
|
||||
cachedBeforeLock.signatureKey === beforeLockSignature.key &&
|
||||
!fs.existsSync(this.getBoardStateLockPath(teamName))
|
||||
) {
|
||||
return { changedTasks: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
const result = this.mutateTeamTasksWithLock(teamName, () => {
|
||||
const beforeSignature = this.readTaskDirectorySignature(teamName);
|
||||
const cached = this.resumeMembersCache.get(teamName);
|
||||
|
|
|
|||
|
|
@ -547,6 +547,44 @@ describe('TeamTaskActivityIntervalService', () => {
|
|||
expect(jsonParseSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('skips the task lock after an unchanged batched resume no-op pass', async () => {
|
||||
await writeTask('alpha', {
|
||||
id: 'bob-task',
|
||||
subject: 'Bob work',
|
||||
owner: 'bob',
|
||||
status: 'in_progress',
|
||||
workIntervals: [{ startedAt: '2026-05-08T10:00:00.000Z' }],
|
||||
historyEvents: [],
|
||||
});
|
||||
|
||||
const service = new TeamTaskActivityIntervalService();
|
||||
expect(
|
||||
service.resumeActiveIntervalsForMembers(
|
||||
'alpha',
|
||||
['bob'],
|
||||
'2026-05-08T10:20:00.000Z'
|
||||
).changedTasks
|
||||
).toBe(0);
|
||||
|
||||
const mutateWithLockSpy = vi.spyOn(
|
||||
TeamTaskActivityIntervalService.prototype as unknown as {
|
||||
mutateTeamTasksWithLock: (
|
||||
teamName: string,
|
||||
run: () => { changedTasks: number; failed?: boolean }
|
||||
) => { changedTasks: number; failed?: boolean };
|
||||
},
|
||||
'mutateTeamTasksWithLock'
|
||||
);
|
||||
const secondResult = service.resumeActiveIntervalsForMembers(
|
||||
'alpha',
|
||||
['bob'],
|
||||
'2026-05-08T10:25:00.000Z'
|
||||
);
|
||||
|
||||
expect(secondResult.changedTasks).toBe(0);
|
||||
expect(mutateWithLockSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('refreshes batched resume cache when a task file changes', async () => {
|
||||
await writeTask('alpha', {
|
||||
id: 'bob-task',
|
||||
|
|
|
|||
Loading…
Reference in a new issue