perf(team): skip data refresh for log activity pulses
This commit is contained in:
parent
b7fa5443fd
commit
abe26ddcc4
2 changed files with 61 additions and 15 deletions
|
|
@ -581,15 +581,19 @@ export function initializeNotificationListeners(): () => void {
|
||||||
};
|
};
|
||||||
const markTaskLogActivity = (teamName: string, taskId: string): void => {
|
const markTaskLogActivity = (teamName: string, taskId: string): void => {
|
||||||
clearTaskLogActivityTimer(teamName, taskId);
|
clearTaskLogActivityTimer(teamName, taskId);
|
||||||
useStore.setState((prev) => ({
|
const isAlreadyActive =
|
||||||
activeTaskLogActivityByTeam: {
|
useStore.getState().activeTaskLogActivityByTeam[teamName]?.[taskId] === true;
|
||||||
...prev.activeTaskLogActivityByTeam,
|
if (!isAlreadyActive) {
|
||||||
[teamName]: {
|
useStore.setState((prev) => ({
|
||||||
...(prev.activeTaskLogActivityByTeam[teamName] ?? {}),
|
activeTaskLogActivityByTeam: {
|
||||||
[taskId]: true,
|
...prev.activeTaskLogActivityByTeam,
|
||||||
|
[teamName]: {
|
||||||
|
...(prev.activeTaskLogActivityByTeam[teamName] ?? {}),
|
||||||
|
[taskId]: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}));
|
||||||
}));
|
}
|
||||||
const timerKey = buildTaskLogActivityTimerKey(teamName, taskId);
|
const timerKey = buildTaskLogActivityTimerKey(teamName, taskId);
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
taskLogActivityTimers.delete(timerKey);
|
taskLogActivityTimers.delete(timerKey);
|
||||||
|
|
@ -1703,9 +1707,13 @@ export function initializeNotificationListeners(): () => void {
|
||||||
seedCurrentRunIdIfMissing();
|
seedCurrentRunIdIfMissing();
|
||||||
const visible = isTeamVisibleInAnyPane(event.teamName);
|
const visible = isTeamVisibleInAnyPane(event.teamName);
|
||||||
if (event.taskId && visible) {
|
if (event.taskId && visible) {
|
||||||
if (isTaskLogActivityChangeEvent(event)) {
|
const isLogActivitySignal = isTaskLogActivityChangeEvent(event);
|
||||||
|
if (isLogActivitySignal) {
|
||||||
markTaskLogActivity(event.teamName, event.taskId);
|
markTaskLogActivity(event.teamName, event.taskId);
|
||||||
}
|
}
|
||||||
|
if (event.taskSignalKind === 'log') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const existingDetailTimer = teamRefreshTimers.get(event.teamName);
|
const existingDetailTimer = teamRefreshTimers.get(event.teamName);
|
||||||
noteTeamRefreshFanout({
|
noteTeamRefreshFanout({
|
||||||
teamName: event.teamName,
|
teamName: event.teamName,
|
||||||
|
|
|
||||||
|
|
@ -1623,7 +1623,7 @@ describe('team change throttling', () => {
|
||||||
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toBeUndefined();
|
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('schedules a bounded team data refresh for visible task log signals', async () => {
|
it('pulses visible task log activity without refreshing team data for explicit log signals', async () => {
|
||||||
const state = useStore.getState();
|
const state = useStore.getState();
|
||||||
const refreshTeamDataSpy = vi.spyOn(state, 'refreshTeamData');
|
const refreshTeamDataSpy = vi.spyOn(state, 'refreshTeamData');
|
||||||
|
|
||||||
|
|
@ -1638,11 +1638,13 @@ describe('team change throttling', () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(refreshTeamDataSpy).not.toHaveBeenCalled();
|
expect(refreshTeamDataSpy).not.toHaveBeenCalled();
|
||||||
|
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toEqual({
|
||||||
|
'task-live': true,
|
||||||
|
});
|
||||||
|
|
||||||
await vi.advanceTimersByTimeAsync(800);
|
await vi.advanceTimersByTimeAsync(800);
|
||||||
|
|
||||||
expect(refreshTeamDataSpy).toHaveBeenCalledTimes(1);
|
expect(refreshTeamDataSpy).not.toHaveBeenCalled();
|
||||||
expect(refreshTeamDataSpy).toHaveBeenCalledWith('my-team', { withDedup: true });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('refreshes visible team data for task change freshness without pulsing live log activity', async () => {
|
it('refreshes visible team data for task change freshness without pulsing live log activity', async () => {
|
||||||
|
|
@ -1667,6 +1669,30 @@ describe('team change throttling', () => {
|
||||||
expect(refreshTeamDataSpy).toHaveBeenCalledWith('my-team', { withDedup: true });
|
expect(refreshTeamDataSpy).toHaveBeenCalledWith('my-team', { withDedup: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps the bounded team data refresh for legacy task log change events', async () => {
|
||||||
|
const state = useStore.getState();
|
||||||
|
const refreshTeamDataSpy = vi.spyOn(state, 'refreshTeamData');
|
||||||
|
|
||||||
|
hoisted.onTeamChangeCb?.(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
type: 'task-log-change',
|
||||||
|
teamName: 'my-team',
|
||||||
|
taskId: 'task-live',
|
||||||
|
detail: 'opencode-runtime-task-event:start',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toEqual({
|
||||||
|
'task-live': true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(800);
|
||||||
|
|
||||||
|
expect(refreshTeamDataSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(refreshTeamDataSpy).toHaveBeenCalledWith('my-team', { withDedup: true });
|
||||||
|
});
|
||||||
|
|
||||||
it('skips the bounded task log refresh if the team is hidden before execution', async () => {
|
it('skips the bounded task log refresh if the team is hidden before execution', async () => {
|
||||||
const state = useStore.getState();
|
const state = useStore.getState();
|
||||||
const refreshTeamDataSpy = vi.spyOn(state, 'refreshTeamData');
|
const refreshTeamDataSpy = vi.spyOn(state, 'refreshTeamData');
|
||||||
|
|
@ -1696,6 +1722,12 @@ describe('team change throttling', () => {
|
||||||
it('extends task log activity pulse on repeated log signals and ignores hidden teams', async () => {
|
it('extends task log activity pulse on repeated log signals and ignores hidden teams', async () => {
|
||||||
const state = useStore.getState();
|
const state = useStore.getState();
|
||||||
const refreshTeamDataSpy = vi.spyOn(state, 'refreshTeamData');
|
const refreshTeamDataSpy = vi.spyOn(state, 'refreshTeamData');
|
||||||
|
const activitySnapshots: Array<Record<string, true> | undefined> = [];
|
||||||
|
const unsubscribeActivitySnapshots = useStore.subscribe((nextState, prevState) => {
|
||||||
|
if (nextState.activeTaskLogActivityByTeam !== prevState.activeTaskLogActivityByTeam) {
|
||||||
|
activitySnapshots.push(nextState.activeTaskLogActivityByTeam['my-team']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
hoisted.onTeamChangeCb?.({}, {
|
hoisted.onTeamChangeCb?.({}, {
|
||||||
type: 'task-log-change',
|
type: 'task-log-change',
|
||||||
|
|
@ -1704,8 +1736,10 @@ describe('team change throttling', () => {
|
||||||
taskSignalKind: 'log',
|
taskSignalKind: 'log',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(activitySnapshots).toEqual([{ 'task-live': true }]);
|
||||||
|
|
||||||
await vi.advanceTimersByTimeAsync(2000);
|
await vi.advanceTimersByTimeAsync(2000);
|
||||||
expect(refreshTeamDataSpy).toHaveBeenCalledTimes(1);
|
expect(refreshTeamDataSpy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
hoisted.onTeamChangeCb?.({}, {
|
hoisted.onTeamChangeCb?.({}, {
|
||||||
type: 'task-log-change',
|
type: 'task-log-change',
|
||||||
|
|
@ -1714,14 +1748,17 @@ describe('team change throttling', () => {
|
||||||
taskSignalKind: 'log',
|
taskSignalKind: 'log',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(activitySnapshots).toEqual([{ 'task-live': true }]);
|
||||||
|
|
||||||
await vi.advanceTimersByTimeAsync(2499);
|
await vi.advanceTimersByTimeAsync(2499);
|
||||||
expect(refreshTeamDataSpy).toHaveBeenCalledTimes(2);
|
expect(refreshTeamDataSpy).not.toHaveBeenCalled();
|
||||||
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toEqual({
|
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toEqual({
|
||||||
'task-live': true,
|
'task-live': true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await vi.advanceTimersByTimeAsync(1);
|
await vi.advanceTimersByTimeAsync(1);
|
||||||
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toBeUndefined();
|
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toBeUndefined();
|
||||||
|
expect(activitySnapshots).toEqual([{ 'task-live': true }, undefined]);
|
||||||
|
|
||||||
useStore.setState({
|
useStore.setState({
|
||||||
paneLayout: {
|
paneLayout: {
|
||||||
|
|
@ -1740,7 +1777,8 @@ describe('team change throttling', () => {
|
||||||
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toBeUndefined();
|
expect(useStore.getState().activeTaskLogActivityByTeam['my-team']).toBeUndefined();
|
||||||
|
|
||||||
await vi.advanceTimersByTimeAsync(800);
|
await vi.advanceTimersByTimeAsync(800);
|
||||||
expect(refreshTeamDataSpy).toHaveBeenCalledTimes(2);
|
expect(refreshTeamDataSpy).not.toHaveBeenCalled();
|
||||||
|
unsubscribeActivitySnapshots();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('applies targeted tool resets without clearing sibling tools', async () => {
|
it('applies targeted tool resets without clearing sibling tools', async () => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue