@@ -12,6 +12,14 @@ const { composeEventPayloadByRepetition } = require('../utils/merge');
1212
1313const MAX_DB_READ_BATCH_SIZE = Number ( process . env . MAX_DB_READ_BATCH_SIZE ) ;
1414
15+ /**
16+ * Chart series labels
17+ */
18+ const ChartType = {
19+ Accepted : 'accepted' ,
20+ RateLimited : 'rate-limited' ,
21+ } ;
22+
1523/**
1624 * @typedef {import('mongodb').UpdateWriteOpResult } UpdateWriteOpResult
1725 */
@@ -449,25 +457,50 @@ class EventsFactory extends Factory {
449457 const days = Math . ceil ( ( end - start ) / ( 24 * 60 * 60 * 1000 ) ) ;
450458
451459 try {
452- const redisData = await this . chartDataService . getProjectChartData (
453- projectId ,
454- startDate ,
455- endDate ,
456- groupBy ,
457- timezoneOffset
458- ) ;
459-
460- if ( redisData && redisData . length > 0 ) {
461- return redisData ;
462- }
463-
464- // Fallback to Mongo (empty groupHash for project-level data)
465- return this . findChartData ( days , timezoneOffset , '' ) ;
460+ const [ acceptedSeries , rateLimitedSeries ] = await Promise . all ( [
461+ this . chartDataService . getProjectChartData (
462+ projectId ,
463+ startDate ,
464+ endDate ,
465+ groupBy ,
466+ timezoneOffset ,
467+ 'events-accepted'
468+ ) ,
469+ this . chartDataService . getProjectChartData (
470+ projectId ,
471+ startDate ,
472+ endDate ,
473+ groupBy ,
474+ timezoneOffset ,
475+ 'events-rate-limited'
476+ ) ,
477+ ] ) ;
478+
479+ return [
480+ {
481+ label : ChartType . Accepted ,
482+ data : acceptedSeries ,
483+ } ,
484+ {
485+ label : ChartType . RateLimited ,
486+ data : rateLimitedSeries ,
487+ } ,
488+ ] ;
466489 } catch ( err ) {
467490 console . error ( '[EventsFactory] getProjectChartData error:' , err ) ;
468491
469- // Fallback to Mongo on error (empty groupHash for project-level data)
470- return this . findChartData ( days , timezoneOffset , '' ) ;
492+ const fallbackAccepted = await this . findChartData ( days , timezoneOffset , '' ) ;
493+
494+ return [
495+ {
496+ label : ChartType . Accepted ,
497+ data : fallbackAccepted ,
498+ } ,
499+ {
500+ label : ChartType . RateLimited ,
501+ data : this . _composeZeroSeries ( fallbackAccepted ) ,
502+ } ,
503+ ] ;
471504 }
472505 }
473506
@@ -480,7 +513,14 @@ class EventsFactory extends Factory {
480513 * @returns {Promise<Array> }
481514 */
482515 async getEventDailyChart ( groupHash , days , timezoneOffset = 0 ) {
483- return this . findChartData ( days , timezoneOffset , groupHash ) ;
516+ const data = await this . findChartData ( days , timezoneOffset , groupHash ) ;
517+
518+ return [
519+ {
520+ label : ChartType . Accepted ,
521+ data,
522+ } ,
523+ ] ;
484524 }
485525
486526 /**
@@ -574,6 +614,23 @@ class EventsFactory extends Factory {
574614 return result ;
575615 }
576616
617+ /**
618+ * Compose zero-filled chart series using timestamps from the provided template
619+ *
620+ * @param {Array<{timestamp: number, count: number}> } template - reference series for timestamps
621+ * @returns {Array<{timestamp: number, count: number}> }
622+ */
623+ _composeZeroSeries ( template = [ ] ) {
624+ if ( ! Array . isArray ( template ) || template . length === 0 ) {
625+ return [ ] ;
626+ }
627+
628+ return template . map ( ( point ) => ( {
629+ timestamp : point . timestamp ,
630+ count : 0 ,
631+ } ) ) ;
632+ }
633+
577634 /**
578635 * Returns number of documents that occurred after the last visit time
579636 *
0 commit comments