Skip to content

Commit 165357c

Browse files
committed
feat(rules): add priority sorting for rule and lock states
Add state comparators and default sorting for all rule tables: - Add ruleStateComparator: STUCK > SUSPENDED > REPLICATING > WAITING_APPROVAL > INJECT > OK > UNKNOWN - Add lockStateComparator: ERROR > STUCK > REPLICATING > OK > UNKNOWN - Apply to Rules List table (state sort by default) - Apply to DID Rules table (state sort by default, add remaining lifetime sort) - Apply to Rule Locks table (state sort by default) This ensures error and stuck states appear first across all tables, helping users quickly identify problematic rules and replicas.
1 parent 699fbd7 commit 165357c

File tree

4 files changed

+83
-7
lines changed

4 files changed

+83
-7
lines changed

src/component-library/pages/DID/details/views/DetailsDIDRules.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import useTableStreaming from '@/lib/infrastructure/hooks/useTableStreaming';
1818
import { formatDate, formatSeconds } from '@/component-library/features/utils/text-formatters';
1919
import { RuleStateBadge } from '@/component-library/features/badges/Rule/RuleStateBadge';
2020
import { NullBadge } from '@/component-library/features/badges/NullBadge';
21-
import { ruleActivityComparator } from '@/lib/core/utils/rule-sorting-utils';
21+
import { ruleActivityComparator, remainingLifetimeComparator, ruleStateComparator } from '@/lib/core/utils/rule-sorting-utils';
2222

2323
type DetailsDIDRulesTableProps = {
2424
streamingHook: UseStreamReader<DIDRulesViewModel>;
@@ -76,6 +76,8 @@ export const DetailsDIDRulesTable = (props: DetailsDIDRulesTableProps) => {
7676
},
7777
filter: true,
7878
filterParams: buildDiscreteFilterParams(Object.values(RuleStateDisplayNames), Object.values(RuleState)),
79+
sortable: true,
80+
comparator: ruleStateComparator,
7981
},
8082
// TODO: minified header with a tooltip
8183
{
@@ -125,16 +127,18 @@ export const DetailsDIDRulesTable = (props: DetailsDIDRulesTableProps) => {
125127
minWidth: 120,
126128
width: 140,
127129
cellRenderer: NullableRemainingLifetime,
130+
sortable: true,
131+
comparator: remainingLifetimeComparator,
128132
},
129133
]);
130134

131135
const onGridReady = (event: GridReadyEvent) => {
132136
props.onGridReady(event);
133-
// Apply default sort to prioritize stuck rules
137+
// Apply default sort to prioritize error/stuck rules
134138
event.api.applyColumnState({
135139
state: [
136140
{
137-
colId: 'locks_stuck_cnt',
141+
colId: 'state',
138142
sort: 'desc',
139143
},
140144
],

src/component-library/pages/Rule/details/DetailsRuleLocks.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { FTSLinkViewModel } from '@/lib/infrastructure/data/view-model/request';
1616
import { useToast } from '@/lib/infrastructure/hooks/useToast';
1717
import { LoadingSpinner } from '@/component-library/atoms/loading/LoadingSpinner';
1818
import { HiExternalLink } from 'react-icons/hi';
19+
import { lockStateComparator } from '@/lib/core/utils/rule-sorting-utils';
1920

2021
type DetailsRuleLocksTableProps = {
2122
streamingHook: UseStreamReader<ListRuleReplicaLockStatesViewModel>;
@@ -150,6 +151,8 @@ const DetailsRuleLocksTable = (props: DetailsRuleLocksTableProps) => {
150151
},
151152
filter: true,
152153
filterParams: buildDiscreteFilterParams(Object.values(LockStateDisplayNames), Object.values(LockState)),
154+
sortable: true,
155+
comparator: lockStateComparator,
153156
},
154157
{
155158
headerName: 'FTS Monitoring',
@@ -159,7 +162,20 @@ const DetailsRuleLocksTable = (props: DetailsRuleLocksTableProps) => {
159162
},
160163
]);
161164

162-
return <StreamedTable columnDefs={columnDefs} tableRef={tableRef} {...props} />;
165+
const onGridReady = (event: GridReadyEvent) => {
166+
props.onGridReady(event);
167+
// Apply default sort to prioritize error/stuck locks
168+
event.api.applyColumnState({
169+
state: [
170+
{
171+
colId: 'state',
172+
sort: 'desc',
173+
},
174+
],
175+
});
176+
};
177+
178+
return <StreamedTable columnDefs={columnDefs} tableRef={tableRef} {...props} onGridReady={onGridReady} />;
163179
};
164180

165181
export const DetailsRuleLocks = ({ id }: { id: string }) => {

src/component-library/pages/Rule/list/ListRuleTable.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { formatDate, formatSeconds } from '@/component-library/features/utils/te
1616
import { RuleStateBadge } from '@/component-library/features/badges/Rule/RuleStateBadge';
1717
import { RuleState } from '@/lib/core/entity/rucio';
1818
import { NullBadge } from '@/component-library/features/badges/NullBadge';
19-
import { ruleActivityComparator, remainingLifetimeComparator } from '@/lib/core/utils/rule-sorting-utils';
19+
import { ruleActivityComparator, remainingLifetimeComparator, ruleStateComparator } from '@/lib/core/utils/rule-sorting-utils';
2020

2121
type ListRuleTableProps = {
2222
streamingHook: UseStreamReader<RuleViewModel>;
@@ -96,6 +96,8 @@ export const ListRuleTable = (props: ListRuleTableProps) => {
9696
},
9797
filter: true,
9898
filterParams: buildDiscreteFilterParams(Object.values(RuleStateDisplayNames), Object.values(RuleState)),
99+
sortable: true,
100+
comparator: ruleStateComparator,
99101
},
100102
// TODO: minified header with a tooltip
101103
{
@@ -153,11 +155,11 @@ export const ListRuleTable = (props: ListRuleTableProps) => {
153155

154156
const onGridReady = (event: GridReadyEvent) => {
155157
props.onGridReady(event);
156-
// Apply default sort to prioritize stuck rules
158+
// Apply default sort to prioritize error/stuck rules
157159
event.api.applyColumnState({
158160
state: [
159161
{
160-
colId: 'locks_stuck_cnt',
162+
colId: 'state',
161163
sort: 'desc',
162164
},
163165
],

src/lib/core/utils/rule-sorting-utils.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,57 @@ export function remainingLifetimeComparator(valueA: number | null | undefined, v
7878
// Numeric comparison (values are in seconds)
7979
return valueA - valueB;
8080
}
81+
82+
/**
83+
* Get priority score for lock states
84+
* Higher scores indicate higher priority (more urgent states)
85+
*/
86+
function getLockStatePriority(state: string): number {
87+
const stateLower = state.toLowerCase();
88+
89+
if (stateLower.includes('error')) return 4;
90+
if (stateLower === 'stuck') return 3;
91+
if (stateLower === 'replicating') return 2;
92+
if (stateLower === 'ok') return 1;
93+
return 0; // unknown or other states
94+
}
95+
96+
/**
97+
* Comparator function for ag-Grid that sorts lock states by priority
98+
* Order: ERROR > STUCK > REPLICATING > OK > UNKNOWN
99+
*/
100+
export function lockStateComparator(valueA: string, valueB: string): number {
101+
const priorityA = getLockStatePriority(valueA);
102+
const priorityB = getLockStatePriority(valueB);
103+
104+
// Higher priority first
105+
return priorityB - priorityA;
106+
}
107+
108+
/**
109+
* Get priority score for rule states
110+
* Higher scores indicate higher priority (more urgent states)
111+
*/
112+
function getRuleStatePriority(state: string): number {
113+
const stateLower = state.toLowerCase();
114+
115+
if (stateLower === 'stuck') return 6;
116+
if (stateLower === 'suspended') return 5;
117+
if (stateLower === 'replicating') return 4;
118+
if (stateLower === 'waiting_approval') return 3;
119+
if (stateLower === 'inject') return 2;
120+
if (stateLower === 'ok') return 1;
121+
return 0; // unknown or other states
122+
}
123+
124+
/**
125+
* Comparator function for ag-Grid that sorts rule states by priority
126+
* Order: STUCK > SUSPENDED > REPLICATING > WAITING_APPROVAL > INJECT > OK > UNKNOWN
127+
*/
128+
export function ruleStateComparator(valueA: string, valueB: string): number {
129+
const priorityA = getRuleStatePriority(valueA);
130+
const priorityB = getRuleStatePriority(valueB);
131+
132+
// Higher priority first
133+
return priorityB - priorityA;
134+
}

0 commit comments

Comments
 (0)