|
1 | 1 | import { getMidnightWithTimezoneOffset, getUTCMidnight } from '../utils/dates'; |
2 | 2 | import safe from 'safe-regex'; |
3 | 3 | import { createProjectEventsByIdLoader } from '../dataLoaders'; |
| 4 | +import RedisHelper from '../redisHelper'; |
| 5 | +import ChartDataService from '../services/chartDataService'; |
4 | 6 |
|
5 | 7 | const Factory = require('./modelFactory'); |
6 | 8 | const mongo = require('../mongo'); |
@@ -85,11 +87,21 @@ class EventsFactory extends Factory { |
85 | 87 |
|
86 | 88 | /** |
87 | 89 | * Creates Event instance |
88 | | - * @param {ObjectId} projectId - project ID |
| 90 | + * @param {ObjectId} projectId |
89 | 91 | */ |
90 | 92 | constructor(projectId) { |
91 | 93 | super(); |
92 | 94 |
|
| 95 | + /** |
| 96 | + * Redis helper instance (singleton) |
| 97 | + */ |
| 98 | + this.redis = RedisHelper.getInstance(); |
| 99 | + |
| 100 | + /** |
| 101 | + * Chart data service for fetching data from Redis TimeSeries |
| 102 | + */ |
| 103 | + this.chartDataService = new ChartDataService(this.redis); |
| 104 | + |
93 | 105 | if (!projectId) { |
94 | 106 | throw new Error('Can not construct Event model, because projectId is not provided'); |
95 | 107 | } |
@@ -280,6 +292,12 @@ class EventsFactory extends Factory { |
280 | 292 | const searchFilter = search.trim().length > 0 |
281 | 293 | ? { |
282 | 294 | $or: [ |
| 295 | + { |
| 296 | + 'repetition.delta': { |
| 297 | + $regex: escapedSearch, |
| 298 | + $options: 'i', |
| 299 | + }, |
| 300 | + }, |
283 | 301 | { |
284 | 302 | 'event.payload.title': { |
285 | 303 | $regex: escapedSearch, |
@@ -414,6 +432,57 @@ class EventsFactory extends Factory { |
414 | 432 | }; |
415 | 433 | } |
416 | 434 |
|
| 435 | + /** |
| 436 | + * Get project chart data from Redis or fallback to MongoDB |
| 437 | + * |
| 438 | + * @param {string} projectId - project ID |
| 439 | + * @param {string} startDate - start date (ISO string) |
| 440 | + * @param {string} endDate - end date (ISO string) |
| 441 | + * @param {number} groupBy - grouping interval in minutes (1=minute, 60=hour, 1440=day) |
| 442 | + * @param {number} timezoneOffset - user's local timezone offset in minutes |
| 443 | + * @returns {Promise<Array>} |
| 444 | + */ |
| 445 | + async getProjectChartData(projectId, startDate, endDate, groupBy = 60, timezoneOffset = 0) { |
| 446 | + // Calculate days for MongoDB fallback |
| 447 | + const start = new Date(startDate).getTime(); |
| 448 | + const end = new Date(endDate).getTime(); |
| 449 | + const days = Math.ceil((end - start) / (24 * 60 * 60 * 1000)); |
| 450 | + |
| 451 | + 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, ''); |
| 466 | + } catch (err) { |
| 467 | + console.error('[EventsFactory] getProjectChartData error:', err); |
| 468 | + |
| 469 | + // Fallback to Mongo on error (empty groupHash for project-level data) |
| 470 | + return this.findChartData(days, timezoneOffset, ''); |
| 471 | + } |
| 472 | + } |
| 473 | + |
| 474 | + /** |
| 475 | + * Get event daily chart data from MongoDB only |
| 476 | + * |
| 477 | + * @param {string} groupHash - event's group hash |
| 478 | + * @param {number} days - how many days to fetch |
| 479 | + * @param {number} timezoneOffset - user's local timezone offset in minutes |
| 480 | + * @returns {Promise<Array>} |
| 481 | + */ |
| 482 | + async getEventDailyChart(groupHash, days, timezoneOffset = 0) { |
| 483 | + return this.findChartData(days, timezoneOffset, groupHash); |
| 484 | + } |
| 485 | + |
417 | 486 | /** |
418 | 487 | * Fetch timestamps and total count of errors (or target error) for each day since |
419 | 488 | * |
@@ -528,7 +597,6 @@ class EventsFactory extends Factory { |
528 | 597 | /** |
529 | 598 | * Returns Event repetitions |
530 | 599 | * |
531 | | - * @param {string|ObjectID} eventId - Event's id, could be repetitionId in case when we want to get repetitions portion by one repetition |
532 | 600 | * @param {string|ObjectID} originalEventId - id of the original event |
533 | 601 | * @param {Number} limit - count limitations |
534 | 602 | * @param {Number} cursor - pointer to the next repetition |
|
0 commit comments