fix(team): keep permission launch updates in store
This commit is contained in:
parent
6ea8b469f0
commit
e309eb8a0d
2 changed files with 73 additions and 1 deletions
|
|
@ -727,6 +727,8 @@ function areMemberSpawnStatusEntriesEqual(
|
|||
): boolean {
|
||||
if (left === right) return true;
|
||||
if (!left || !right) return left === right;
|
||||
const leftPendingPermissionIds = [...(left.pendingPermissionRequestIds ?? [])].sort();
|
||||
const rightPendingPermissionIds = [...(right.pendingPermissionRequestIds ?? [])].sort();
|
||||
// Renderer equality intentionally ignores raw timing fields that do not change
|
||||
// visible member status. This suppresses heartbeat-only churn in TeamDetailView.
|
||||
return (
|
||||
|
|
@ -738,7 +740,9 @@ function areMemberSpawnStatusEntriesEqual(
|
|||
left.runtimeAlive === right.runtimeAlive &&
|
||||
left.runtimeModel === right.runtimeModel &&
|
||||
left.bootstrapConfirmed === right.bootstrapConfirmed &&
|
||||
left.hardFailure === right.hardFailure
|
||||
left.hardFailure === right.hardFailure &&
|
||||
leftPendingPermissionIds.length === rightPendingPermissionIds.length &&
|
||||
leftPendingPermissionIds.every((value, index) => value === rightPendingPermissionIds[index])
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3612,6 +3612,74 @@ describe('teamSlice actions', () => {
|
|||
expect(store.getState().memberSpawnSnapshotsByTeam['my-team']).toBe(previousSnapshot);
|
||||
});
|
||||
|
||||
it('does not suppress spawn snapshots when pending permission request ids change', async () => {
|
||||
const store = createSliceStore();
|
||||
const previousSnapshot = createMemberSpawnSnapshot({
|
||||
teamLaunchState: 'partial_pending',
|
||||
launchPhase: 'active',
|
||||
summary: {
|
||||
confirmedCount: 0,
|
||||
pendingCount: 1,
|
||||
failedCount: 0,
|
||||
runtimeAlivePendingCount: 0,
|
||||
},
|
||||
statuses: {
|
||||
alice: createMemberSpawnStatus({
|
||||
status: 'waiting',
|
||||
launchState: 'runtime_pending_bootstrap',
|
||||
runtimeAlive: false,
|
||||
livenessSource: undefined,
|
||||
bootstrapConfirmed: false,
|
||||
firstSpawnAcceptedAt: '2026-03-12T09:59:30.000Z',
|
||||
lastHeartbeatAt: undefined,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
store.setState({
|
||||
memberSpawnStatusesByTeam: {
|
||||
'my-team': previousSnapshot.statuses,
|
||||
},
|
||||
memberSpawnSnapshotsByTeam: {
|
||||
'my-team': previousSnapshot,
|
||||
},
|
||||
});
|
||||
|
||||
const nextSnapshot = createMemberSpawnSnapshot({
|
||||
teamLaunchState: 'partial_pending',
|
||||
launchPhase: 'active',
|
||||
summary: {
|
||||
confirmedCount: 0,
|
||||
pendingCount: 1,
|
||||
failedCount: 0,
|
||||
runtimeAlivePendingCount: 0,
|
||||
},
|
||||
statuses: {
|
||||
alice: createMemberSpawnStatus({
|
||||
status: 'waiting',
|
||||
launchState: 'runtime_pending_bootstrap',
|
||||
runtimeAlive: false,
|
||||
livenessSource: undefined,
|
||||
bootstrapConfirmed: false,
|
||||
firstSpawnAcceptedAt: '2026-03-12T09:59:30.000Z',
|
||||
lastHeartbeatAt: undefined,
|
||||
pendingPermissionRequestIds: ['perm-1'],
|
||||
}),
|
||||
},
|
||||
});
|
||||
hoisted.getMemberSpawnStatuses.mockResolvedValue(nextSnapshot);
|
||||
|
||||
await store.getState().fetchMemberSpawnStatuses('my-team');
|
||||
|
||||
expect(store.getState().memberSpawnSnapshotsByTeam['my-team']).not.toBe(previousSnapshot);
|
||||
expect(store.getState().memberSpawnStatusesByTeam['my-team']).not.toBe(
|
||||
previousSnapshot.statuses
|
||||
);
|
||||
expect(
|
||||
store.getState().memberSpawnStatusesByTeam['my-team']?.alice?.pendingPermissionRequestIds
|
||||
).toEqual(['perm-1']);
|
||||
});
|
||||
|
||||
it('ignores stale spawn-status fetches after runtime already went offline', async () => {
|
||||
const store = createSliceStore();
|
||||
store.setState({
|
||||
|
|
|
|||
Loading…
Reference in a new issue