1- import React , { useMemo , useReducer , useState } from 'react'
1+ import React , { useEffect , useMemo , useReducer , useState } from 'react'
22import {
33 Alert ,
44 Badge ,
@@ -25,8 +25,15 @@ import {IconArrowDown, IconArrowUp, IconArrowUpDown, IconWarning} from '../compo
2525import { Labels , labelsString , MetricName , parseLabels } from '../labels'
2626import { createConnectTransport , createPromiseClient } from '@bufbuild/connect-web'
2727import { ObjectiveService } from '../proto/objectives/v1alpha1/objectives_connectweb'
28- import { Objective , ObjectiveStatus } from '../proto/objectives/v1alpha1/objectives_pb'
29- import { useObjectivesList } from '../objectives'
28+ import {
29+ Alert as ObjectiveAlert ,
30+ Alert_State ,
31+ GetAlertsResponse ,
32+ GetStatusResponse ,
33+ ListResponse ,
34+ Objective ,
35+ ObjectiveStatus ,
36+ } from '../proto/objectives/v1alpha1/objectives_pb'
3037
3138enum TableObjectiveState {
3239 Unknown ,
@@ -246,22 +253,12 @@ const List = () => {
246253 )
247254 } , [ ] )
248255
249- // const promClient = useMemo(() => {
250- // return createPromiseClient(
251- // PrometheusService,
252- // // createGrpcWebTransport({ TODO: Use grpcWeb in production for efficiency?
253- // createConnectTransport({
254- // baseUrl: API_BASEPATH,
255- // }),
256- // )
257- // }, [])
258-
259256 const navigate = useNavigate ( )
260257 const { search} = useLocation ( )
261258
262259 const [ objectives , setObjectives ] = useState < Objective [ ] > ( [ ] )
263260 const initialTableState : TableState = { objectives : { } }
264- const [ table ] = useReducer ( tableReducer , initialTableState )
261+ const [ table , dispatchTable ] = useReducer ( tableReducer , initialTableState )
265262 const [ tableSortState , setTableSortState ] = useState < TableSorting > ( {
266263 type : TableSortType . Budget ,
267264 order : TableSortOrder . Ascending ,
@@ -311,113 +308,97 @@ const List = () => {
311308 navigate ( `?filter=${ encodeURI ( labelsString ( updatedFilter ) ) } ` )
312309 }
313310
314- // useEffect(() => {
315- // document.title = 'Objectives - Pyrra'
316- // })
317- ¡
318- // const {response, status} = useObjectivesList(client, labelsString(filterLabels), '')
319- // if (status === 'success' && response !== null) {
320- // console.log(response.objectives)
321- // setObjectives(response.objectives)
322- // }
323-
324- // const objectiveQueries = useQueries(
325- // objectives.map((objective: Objective) => {
326- // return {
327- // queryKey: ['objective', labelsString(objective.labels)],
328- // queryFn: async () => {
329- // return await client.getStatus({expr: labelsString(objective.labels)})
330- // },
331- // }
332- // }),
333- // )
334- //
335- // objectiveQueries.forEach((q) => {
336- // console.log(q)
337- // })
338-
339- // useEffect(() => {
340- // // const controller = new AbortController()
341- // // const signal = controller.signal // TODO: Pass this to the generated fetch client?
342- //
343- // // First we need to make sure to have objectives before we try fetching alerts for them.
344- // // If we were to do this concurrently it may end up in a situation
345- // // where we try to add an alert for a not yet existing objective.
346- // // TODO: This is prone to a concurrency race with updates of status that have additional groupings...
347- // // One solution would be to store this in a separate array and reconcile against that array after every status update.
348- // if (objectives.length > 0) {
349- // client
350- // .getAlerts({
351- // expr: '',
352- // inactive: false,
353- // current: false,
354- // })
355- // .then((resp: GetAlertsResponse) => {
356- // resp.alerts.forEach((a: ObjectiveAlert) => {
357- // if (a.state === Alert_State.firing) {
358- // dispatchTable({
359- // type: TableActionType.SetAlert,
360- // labels: a.labels,
361- // severity: a.severity,
362- // })
363- // }
364- // })
365- // })
366- // .catch((err) => console.log(err))
367- // }
368- //
369- // objectives
370- // .sort((a: Objective, b: Objective) =>
371- // labelsString(a.labels).localeCompare(labelsString(b.labels)),
372- // )
373- // .forEach((o: Objective) => {
374- // dispatchTable({
375- // type: TableActionType.SetObjective,
376- // lset: labelsString(o.labels),
377- // objective: o,
378- // })
379- //
380- // client
381- // .getStatus({expr: labelsString(o.labels)})
382- // .then((resp: GetStatusResponse) => {
383- // if (resp.status.length === 0) {
384- // dispatchTable({type: TableActionType.SetStatusNone, lset: labelsString(o.labels)})
385- // } else if (resp.status.length === 1) {
386- // dispatchTable({
387- // type: TableActionType.SetStatus,
388- // lset: labelsString(o.labels),
389- // status: resp.status[0],
390- // })
391- // } else {
392- // dispatchTable({type: TableActionType.DeleteObjective, lset: labelsString(o.labels)})
393- //
394- // resp.status.forEach((s: ObjectiveStatus) => {
395- // const so = o.clone()
396- // // Identify by the combined labels
397- // const sLabels: Labels = s.labels !== undefined ? s.labels : {}
398- // const soLabels: Labels = {...o.labels, ...sLabels}
399- //
400- // dispatchTable({
401- // type: TableActionType.SetObjectiveWithStatus,
402- // lset: labelsString(soLabels),
403- // statusLabels: sLabels,
404- // objective: so,
405- // status: s,
406- // })
407- // })
408- // }
409- // })
410- // .catch((err) => {
411- // console.log(err)
412- // dispatchTable({type: TableActionType.SetStatusError, lset: labelsString(o.labels)})
413- // })
414- // })
415- //
416- // // return () => {
417- // // // cancel pending requests if necessary
418- // // controller.abort()
419- // // }
420- // }, [client, objectives])
311+ useEffect ( ( ) => {
312+ document . title = 'Objectives - Pyrra'
313+
314+ client
315+ . list ( { expr : labelsString ( filterLabels ) } )
316+ . then ( ( resp : ListResponse ) => setObjectives ( resp . objectives ) )
317+ . catch ( ( err ) => console . log ( err ) )
318+ } , [ client , filterLabels ] )
319+
320+ useEffect ( ( ) => {
321+ // const controller = new AbortController()
322+ // const signal = controller.signal // TODO: Pass this to the generated fetch client?
323+
324+ // First we need to make sure to have objectives before we try fetching alerts for them.
325+ // If we were to do this concurrently it may end up in a situation
326+ // where we try to add an alert for a not yet existing objective.
327+ // TODO: This is prone to a concurrency race with updates of status that have additional groupings...
328+ // One solution would be to store this in a separate array and reconcile against that array after every status update.
329+ if ( objectives . length > 0 ) {
330+ client
331+ . getAlerts ( {
332+ expr : '' ,
333+ inactive : false ,
334+ current : false ,
335+ } )
336+ . then ( ( resp : GetAlertsResponse ) => {
337+ resp . alerts . forEach ( ( a : ObjectiveAlert ) => {
338+ if ( a . state === Alert_State . firing ) {
339+ dispatchTable ( {
340+ type : TableActionType . SetAlert ,
341+ labels : a . labels ,
342+ severity : a . severity ,
343+ } )
344+ }
345+ } )
346+ } )
347+ . catch ( ( err ) => console . log ( err ) )
348+ }
349+
350+ objectives
351+ . sort ( ( a : Objective , b : Objective ) =>
352+ labelsString ( a . labels ) . localeCompare ( labelsString ( b . labels ) ) ,
353+ )
354+ . forEach ( ( o : Objective ) => {
355+ dispatchTable ( {
356+ type : TableActionType . SetObjective ,
357+ lset : labelsString ( o . labels ) ,
358+ objective : o ,
359+ } )
360+
361+ client
362+ . getStatus ( { expr : labelsString ( o . labels ) } )
363+ . then ( ( resp : GetStatusResponse ) => {
364+ if ( resp . status . length === 0 ) {
365+ dispatchTable ( { type : TableActionType . SetStatusNone , lset : labelsString ( o . labels ) } )
366+ } else if ( resp . status . length === 1 ) {
367+ dispatchTable ( {
368+ type : TableActionType . SetStatus ,
369+ lset : labelsString ( o . labels ) ,
370+ status : resp . status [ 0 ] ,
371+ } )
372+ } else {
373+ dispatchTable ( { type : TableActionType . DeleteObjective , lset : labelsString ( o . labels ) } )
374+
375+ resp . status . forEach ( ( s : ObjectiveStatus ) => {
376+ const so = o . clone ( )
377+ // Identify by the combined labels
378+ const sLabels : Labels = s . labels !== undefined ? s . labels : { }
379+ const soLabels : Labels = { ...o . labels , ...sLabels }
380+
381+ dispatchTable ( {
382+ type : TableActionType . SetObjectiveWithStatus ,
383+ lset : labelsString ( soLabels ) ,
384+ statusLabels : sLabels ,
385+ objective : so ,
386+ status : s ,
387+ } )
388+ } )
389+ }
390+ } )
391+ . catch ( ( err ) => {
392+ console . log ( err )
393+ dispatchTable ( { type : TableActionType . SetStatusError , lset : labelsString ( o . labels ) } )
394+ } )
395+ } )
396+
397+ // return () => {
398+ // // cancel pending requests if necessary
399+ // controller.abort()
400+ // }
401+ } , [ client , objectives ] )
421402
422403 const handleTableSort = ( e : any , type : TableSortType ) : void => {
423404 e . preventDefault ( )
0 commit comments