@@ -61,11 +61,13 @@ export type ErrorOccurrenceActivity = ErrorOccurrences["data"][string];
6161type ErrorGroupCursor = {
6262 occurrenceCount : number ;
6363 fingerprint : string ;
64+ taskIdentifier : string ;
6465} ;
6566
6667const ErrorGroupCursorSchema = z . object ( {
6768 occurrenceCount : z . number ( ) ,
6869 fingerprint : z . string ( ) ,
70+ taskIdentifier : z . string ( ) ,
6971} ) ;
7072
7173function encodeCursor ( cursor : ErrorGroupCursor ) : string {
@@ -191,19 +193,22 @@ export class ErrorsListPresenter extends BasePresenter {
191193 ) ;
192194 }
193195
194- // Cursor-based pagination (sorted by occurrence_count DESC)
196+ // Cursor-based pagination (sorted by occurrence_count DESC, then fingerprint, then task )
195197 const decodedCursor = cursor ? decodeCursor ( cursor ) : null ;
196198 if ( decodedCursor ) {
197199 queryBuilder . having (
198- "(occurrence_count < {cursorOccurrenceCount: UInt64} OR (occurrence_count = {cursorOccurrenceCount: UInt64} AND error_fingerprint < {cursorFingerprint: String}))" ,
200+ `(occurrence_count < {cursorOccurrenceCount: UInt64}
201+ OR (occurrence_count = {cursorOccurrenceCount: UInt64} AND error_fingerprint < {cursorFingerprint: String})
202+ OR (occurrence_count = {cursorOccurrenceCount: UInt64} AND error_fingerprint = {cursorFingerprint: String} AND task_identifier < {cursorTaskIdentifier: String}))` ,
199203 {
200204 cursorOccurrenceCount : decodedCursor . occurrenceCount ,
201205 cursorFingerprint : decodedCursor . fingerprint ,
206+ cursorTaskIdentifier : decodedCursor . taskIdentifier ,
202207 }
203208 ) ;
204209 }
205210
206- queryBuilder . orderBy ( "occurrence_count DESC, error_fingerprint DESC" ) ;
211+ queryBuilder . orderBy ( "task_identifier DESC, error_fingerprint DESC, occurrence_count DESC" ) ;
207212 queryBuilder . limit ( pageSize + 1 ) ;
208213
209214 const [ queryError , records ] = await queryBuilder . execute ( ) ;
@@ -222,6 +227,7 @@ export class ErrorsListPresenter extends BasePresenter {
222227 nextCursor = encodeCursor ( {
223228 occurrenceCount : lastError . occurrence_count ,
224229 fingerprint : lastError . error_fingerprint ,
230+ taskIdentifier : lastError . task_identifier ,
225231 } ) ;
226232 }
227233
@@ -364,10 +370,16 @@ export class ErrorsListPresenter extends BasePresenter {
364370 if ( queryError || ! records ) return result ;
365371
366372 for ( const record of records ) {
367- result . set ( record . error_fingerprint , {
368- firstSeen : parseClickHouseDateTime ( record . first_seen ) ,
369- lastSeen : parseClickHouseDateTime ( record . last_seen ) ,
370- } ) ;
373+ const firstSeen = parseClickHouseDateTime ( record . first_seen ) ;
374+ const lastSeen = parseClickHouseDateTime ( record . last_seen ) ;
375+ const existing = result . get ( record . error_fingerprint ) ;
376+
377+ if ( existing ) {
378+ if ( firstSeen < existing . firstSeen ) existing . firstSeen = firstSeen ;
379+ if ( lastSeen > existing . lastSeen ) existing . lastSeen = lastSeen ;
380+ } else {
381+ result . set ( record . error_fingerprint , { firstSeen, lastSeen } ) ;
382+ }
371383 }
372384
373385 return result ;
0 commit comments