refactor(team): extract data request keys
This commit is contained in:
parent
1d2f61ad86
commit
69f7a21771
3 changed files with 106 additions and 34 deletions
|
|
@ -29,6 +29,14 @@ import {
|
||||||
isTeamTaskNeedsFixActionable,
|
isTeamTaskNeedsFixActionable,
|
||||||
} from '@shared/utils/teamTaskState';
|
} from '@shared/utils/teamTaskState';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getFullTeamDataRequestKey,
|
||||||
|
getTeamDataRequestKey,
|
||||||
|
getTeamDataRequestLabel,
|
||||||
|
getThinTeamDataRequestKey,
|
||||||
|
isTeamDataRequestKeyForTeam,
|
||||||
|
normalizeTeamGetDataOptions,
|
||||||
|
} from '../team/teamDataRequestKeys';
|
||||||
import { selectTeamDataForName } from '../team/teamDataSelectors';
|
import { selectTeamDataForName } from '../team/teamDataSelectors';
|
||||||
import {
|
import {
|
||||||
areInboxMessageArraysEquivalent,
|
areInboxMessageArraysEquivalent,
|
||||||
|
|
@ -155,38 +163,6 @@ interface RefreshTeamDataOptions {
|
||||||
withDedup?: boolean;
|
withDedup?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type TeamDataSnapshotMode = 'full' | 'thin';
|
|
||||||
|
|
||||||
function normalizeTeamGetDataOptions(options?: TeamGetDataOptions): TeamGetDataOptions | undefined {
|
|
||||||
return options?.includeMemberBranches === false ? { includeMemberBranches: false } : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldIncludeMemberBranches(options?: TeamGetDataOptions): boolean {
|
|
||||||
return normalizeTeamGetDataOptions(options)?.includeMemberBranches !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTeamDataSnapshotMode(options?: TeamGetDataOptions): TeamDataSnapshotMode {
|
|
||||||
return shouldIncludeMemberBranches(options) ? 'full' : 'thin';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTeamDataRequestKey(teamName: string, options?: TeamGetDataOptions): string {
|
|
||||||
const normalizedOptions = normalizeTeamGetDataOptions(options);
|
|
||||||
return `${teamName}\u0000mode:${getTeamDataSnapshotMode(normalizedOptions)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTeamDataRequestLabel(teamName: string, options?: TeamGetDataOptions): string {
|
|
||||||
const normalizedOptions = normalizeTeamGetDataOptions(options);
|
|
||||||
return `team:getData(${teamName},mode=${getTeamDataSnapshotMode(normalizedOptions)})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFullTeamDataRequestKey(teamName: string): string {
|
|
||||||
return getTeamDataRequestKey(teamName);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getThinTeamDataRequestKey(teamName: string): string {
|
|
||||||
return getTeamDataRequestKey(teamName, { includeMemberBranches: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasFullTeamDataRequestForTeam(teamName: string): boolean {
|
function hasFullTeamDataRequestForTeam(teamName: string): boolean {
|
||||||
return inFlightTeamDataRequests.has(getFullTeamDataRequestKey(teamName));
|
return inFlightTeamDataRequests.has(getFullTeamDataRequestKey(teamName));
|
||||||
}
|
}
|
||||||
|
|
@ -196,9 +172,8 @@ function hasThinTeamDataRequestForTeam(teamName: string): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearTeamDataRequestsForTeam(teamName: string): void {
|
function clearTeamDataRequestsForTeam(teamName: string): void {
|
||||||
const prefix = `${teamName}\u0000`;
|
|
||||||
for (const key of inFlightTeamDataRequests.keys()) {
|
for (const key of inFlightTeamDataRequests.keys()) {
|
||||||
if (key.startsWith(prefix)) {
|
if (isTeamDataRequestKeyForTeam(key, teamName)) {
|
||||||
inFlightTeamDataRequests.delete(key);
|
inFlightTeamDataRequests.delete(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
src/renderer/store/team/teamDataRequestKeys.ts
Normal file
39
src/renderer/store/team/teamDataRequestKeys.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import type { TeamGetDataOptions } from '@shared/types';
|
||||||
|
|
||||||
|
export type TeamDataSnapshotMode = 'full' | 'thin';
|
||||||
|
|
||||||
|
export function normalizeTeamGetDataOptions(
|
||||||
|
options?: TeamGetDataOptions
|
||||||
|
): TeamGetDataOptions | undefined {
|
||||||
|
return options?.includeMemberBranches === false ? { includeMemberBranches: false } : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shouldIncludeMemberBranches(options?: TeamGetDataOptions): boolean {
|
||||||
|
return normalizeTeamGetDataOptions(options)?.includeMemberBranches !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTeamDataSnapshotMode(options?: TeamGetDataOptions): TeamDataSnapshotMode {
|
||||||
|
return shouldIncludeMemberBranches(options) ? 'full' : 'thin';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTeamDataRequestKey(teamName: string, options?: TeamGetDataOptions): string {
|
||||||
|
const normalizedOptions = normalizeTeamGetDataOptions(options);
|
||||||
|
return `${teamName}\u0000mode:${getTeamDataSnapshotMode(normalizedOptions)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTeamDataRequestLabel(teamName: string, options?: TeamGetDataOptions): string {
|
||||||
|
const normalizedOptions = normalizeTeamGetDataOptions(options);
|
||||||
|
return `team:getData(${teamName},mode=${getTeamDataSnapshotMode(normalizedOptions)})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFullTeamDataRequestKey(teamName: string): string {
|
||||||
|
return getTeamDataRequestKey(teamName);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getThinTeamDataRequestKey(teamName: string): string {
|
||||||
|
return getTeamDataRequestKey(teamName, { includeMemberBranches: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isTeamDataRequestKeyForTeam(requestKey: string, teamName: string): boolean {
|
||||||
|
return requestKey.startsWith(`${teamName}\u0000`);
|
||||||
|
}
|
||||||
58
test/renderer/store/teamDataRequestKeys.test.ts
Normal file
58
test/renderer/store/teamDataRequestKeys.test.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getFullTeamDataRequestKey,
|
||||||
|
getTeamDataRequestKey,
|
||||||
|
getTeamDataRequestLabel,
|
||||||
|
getTeamDataSnapshotMode,
|
||||||
|
getThinTeamDataRequestKey,
|
||||||
|
isTeamDataRequestKeyForTeam,
|
||||||
|
normalizeTeamGetDataOptions,
|
||||||
|
shouldIncludeMemberBranches,
|
||||||
|
} from '../../../src/renderer/store/team/teamDataRequestKeys';
|
||||||
|
|
||||||
|
describe('teamDataRequestKeys', () => {
|
||||||
|
it('normalizes only the thin snapshot option and treats all other inputs as full snapshots', () => {
|
||||||
|
expect(normalizeTeamGetDataOptions()).toBeUndefined();
|
||||||
|
expect(normalizeTeamGetDataOptions({})).toBeUndefined();
|
||||||
|
expect(normalizeTeamGetDataOptions({ includeMemberBranches: true })).toBeUndefined();
|
||||||
|
expect(normalizeTeamGetDataOptions({ includeMemberBranches: false })).toEqual({
|
||||||
|
includeMemberBranches: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(shouldIncludeMemberBranches()).toBe(true);
|
||||||
|
expect(shouldIncludeMemberBranches({ includeMemberBranches: true })).toBe(true);
|
||||||
|
expect(shouldIncludeMemberBranches({ includeMemberBranches: false })).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('maps normalized request options to stable full and thin snapshot modes', () => {
|
||||||
|
expect(getTeamDataSnapshotMode()).toBe('full');
|
||||||
|
expect(getTeamDataSnapshotMode({ includeMemberBranches: true })).toBe('full');
|
||||||
|
expect(getTeamDataSnapshotMode({ includeMemberBranches: false })).toBe('thin');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('builds request keys that preserve the existing null-separated team/mode contract', () => {
|
||||||
|
expect(getTeamDataRequestKey('my-team')).toBe('my-team\u0000mode:full');
|
||||||
|
expect(getTeamDataRequestKey('my-team', { includeMemberBranches: true })).toBe(
|
||||||
|
'my-team\u0000mode:full'
|
||||||
|
);
|
||||||
|
expect(getTeamDataRequestKey('my-team', { includeMemberBranches: false })).toBe(
|
||||||
|
'my-team\u0000mode:thin'
|
||||||
|
);
|
||||||
|
expect(getFullTeamDataRequestKey('my-team')).toBe('my-team\u0000mode:full');
|
||||||
|
expect(getThinTeamDataRequestKey('my-team')).toBe('my-team\u0000mode:thin');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('builds timeout/debug labels from the same normalized mode policy', () => {
|
||||||
|
expect(getTeamDataRequestLabel('my-team')).toBe('team:getData(my-team,mode=full)');
|
||||||
|
expect(getTeamDataRequestLabel('my-team', { includeMemberBranches: false })).toBe(
|
||||||
|
'team:getData(my-team,mode=thin)'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('matches request keys only for the exact team prefix boundary', () => {
|
||||||
|
expect(isTeamDataRequestKeyForTeam('my-team\u0000mode:full', 'my-team')).toBe(true);
|
||||||
|
expect(isTeamDataRequestKeyForTeam('my-team-extra\u0000mode:full', 'my-team')).toBe(false);
|
||||||
|
expect(isTeamDataRequestKeyForTeam('my-team', 'my-team')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue