@oneuptime/common 7.0.3815 → 7.0.3826

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/Models/DatabaseModels/AlertStateTimeline.ts +1 -1
  2. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -1
  3. package/Models/DatabaseModels/MonitorStatusTimeline.ts +1 -1
  4. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -1
  5. package/Models/DatabaseModels/WorkspaceNotificationRule.ts +8 -0
  6. package/Server/Services/AlertStateTimelineService.ts +192 -86
  7. package/Server/Services/IncidentStateTimelineService.ts +205 -103
  8. package/Server/Services/MonitorStatusTimelineService.ts +202 -101
  9. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +201 -101
  10. package/UI/Components/Forms/BasicForm.tsx +4 -0
  11. package/UI/Components/Forms/Types/Field.ts +3 -0
  12. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -1
  13. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
  14. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -1
  15. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  16. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +1 -1
  17. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
  18. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -1
  19. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  20. package/build/dist/Models/DatabaseModels/WorkspaceNotificationRule.js +8 -0
  21. package/build/dist/Models/DatabaseModels/WorkspaceNotificationRule.js.map +1 -1
  22. package/build/dist/Server/Services/AlertStateTimelineService.js +171 -72
  23. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  24. package/build/dist/Server/Services/IncidentStateTimelineService.js +171 -73
  25. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  26. package/build/dist/Server/Services/MonitorStatusTimelineService.js +168 -72
  27. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  28. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +174 -80
  29. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  30. package/build/dist/UI/Components/Forms/BasicForm.js +3 -0
  31. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  32. package/package.json +2 -2
@@ -19,7 +19,7 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
19
19
  public constructor() {
20
20
  super(MonitorStatusTimeline);
21
21
  if (IsBillingEnabled) {
22
- this.hardDeleteItemsOlderThanInDays("createdAt", 120);
22
+ this.hardDeleteItemsOlderThanInDays("startsAt", 120);
23
23
  }
24
24
  }
25
25
 
@@ -71,31 +71,64 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
71
71
  }
72
72
  }
73
73
 
74
- const lastMonitorStatusTimeline: MonitorStatusTimeline | null =
75
- await this.findOneBy({
76
- query: {
77
- monitorId: createBy.data.monitorId,
78
- },
79
- sort: {
80
- createdAt: SortOrder.Descending,
81
- },
82
- props: {
83
- isRoot: true,
84
- },
85
- select: {
86
- _id: true,
87
- },
88
- });
74
+ const stateBeforeThis: MonitorStatusTimeline | null = await this.findOneBy({
75
+ query: {
76
+ monitorId: createBy.data.monitorId,
77
+ startsAt: QueryHelper.lessThanEqualTo(createBy.data.startsAt),
78
+ },
79
+ sort: {
80
+ startsAt: SortOrder.Descending,
81
+ },
82
+ props: {
83
+ isRoot: true,
84
+ },
85
+ select: {
86
+ monitorStatusId: true,
87
+ startsAt: true,
88
+ endsAt: true,
89
+ },
90
+ });
89
91
 
90
- if (!lastMonitorStatusTimeline) {
92
+ logger.debug("State Before this");
93
+ logger.debug(stateBeforeThis);
94
+
95
+ // If this is the first state, then do not notify the owner.
96
+ if (!stateBeforeThis) {
91
97
  // since this is the first status, do not notify the owner.
92
98
  createBy.data.isOwnerNotified = true;
93
99
  }
94
100
 
101
+ const stateAfterThis: MonitorStatusTimeline | null = await this.findOneBy({
102
+ query: {
103
+ monitorId: createBy.data.monitorId,
104
+ startsAt: QueryHelper.greaterThan(createBy.data.startsAt),
105
+ },
106
+ sort: {
107
+ startsAt: SortOrder.Ascending,
108
+ },
109
+ props: {
110
+ isRoot: true,
111
+ },
112
+ select: {
113
+ monitorStatusId: true,
114
+ startsAt: true,
115
+ endsAt: true,
116
+ },
117
+ });
118
+
119
+ // compute ends at. It's the start of the next status.
120
+ if (stateAfterThis && stateAfterThis.startsAt) {
121
+ createBy.data.endsAt = stateAfterThis.startsAt;
122
+ }
123
+
124
+ logger.debug("State After this");
125
+ logger.debug(stateAfterThis);
126
+
95
127
  return {
96
128
  createBy,
97
129
  carryForward: {
98
- lastMonitorStatusTimelineId: lastMonitorStatusTimeline?.id || null,
130
+ statusTimelineBeforeThisStatus: stateBeforeThis || null,
131
+ statusTimelineAfterThisStatus: stateAfterThis || null,
99
132
  mutex: mutex,
100
133
  },
101
134
  };
@@ -115,27 +148,72 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
115
148
 
116
149
  // update the last status as ended.
117
150
 
118
- if (onCreate.carryForward.lastMonitorStatusTimelineId) {
151
+ logger.debug("Status Timeline Before this");
152
+ logger.debug(onCreate.carryForward.statusTimelineBeforeThisStatus);
153
+
154
+ logger.debug("Status Timeline After this");
155
+ logger.debug(onCreate.carryForward.statusTimelineAfterThisStatus);
156
+
157
+ logger.debug("Created Item");
158
+ logger.debug(createdItem);
159
+
160
+ // now there are three cases.
161
+ // 1. This is the first status OR there's no status after this.
162
+ if (!onCreate.carryForward.statusTimelineBeforeThisStatus) {
163
+ // This is the first status, no need to update previous status.
164
+ logger.debug("This is the first status.");
165
+ } else if (!onCreate.carryForward.statusTimelineAfterThisStatus) {
166
+ // 2. This is the last status.
167
+ // Update the previous status to end at the start of this status.
119
168
  await this.updateOneById({
120
- id: onCreate.carryForward.lastMonitorStatusTimelineId!,
169
+ id: onCreate.carryForward.statusTimelineBeforeThisStatus.id!,
121
170
  data: {
122
- endsAt: createdItem.createdAt || OneUptimeDate.getCurrentDate(),
171
+ endsAt: createdItem.startsAt!,
123
172
  },
124
173
  props: {
125
174
  isRoot: true,
126
175
  },
127
176
  });
177
+ logger.debug("This is the last status.");
178
+ } else {
179
+ // 3. This is in the middle.
180
+ // Update the previous status to end at the start of this status.
181
+ await this.updateOneById({
182
+ id: onCreate.carryForward.statusTimelineBeforeThisStatus.id!,
183
+ data: {
184
+ endsAt: createdItem.startsAt!,
185
+ },
186
+ props: {
187
+ isRoot: true,
188
+ },
189
+ });
190
+
191
+ // Update the next status to start at the end of this status.
192
+ await this.updateOneById({
193
+ id: onCreate.carryForward.statusTimelineAfterThisStatus.id!,
194
+ data: {
195
+ startsAt: createdItem.endsAt!,
196
+ },
197
+ props: {
198
+ isRoot: true,
199
+ },
200
+ });
201
+ logger.debug("This status is in the middle.");
128
202
  }
129
203
 
130
- await MonitorService.updateOneBy({
131
- query: {
132
- _id: createdItem.monitorId?.toString(),
133
- },
134
- data: {
135
- currentMonitorStatusId: createdItem.monitorStatusId,
136
- },
137
- props: onCreate.createBy.props,
138
- });
204
+ if (!createdItem.endsAt) {
205
+ // if this is the last status, then update the monitor status.
206
+
207
+ await MonitorService.updateOneBy({
208
+ query: {
209
+ _id: createdItem.monitorId?.toString(),
210
+ },
211
+ data: {
212
+ currentMonitorStatusId: createdItem.monitorStatusId,
213
+ },
214
+ props: onCreate.createBy.props,
215
+ });
216
+ }
139
217
 
140
218
  if (onCreate.carryForward.mutex) {
141
219
  const mutex: SemaphoreMutex = onCreate.carryForward.mutex;
@@ -155,6 +233,7 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
155
233
  select: {
156
234
  monitorId: true,
157
235
  startsAt: true,
236
+ endsAt: true,
158
237
  },
159
238
  props: {
160
239
  isRoot: true,
@@ -174,82 +253,104 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
174
253
  },
175
254
  });
176
255
 
256
+ if (!monitorStatusTimelineToBeDeleted) {
257
+ throw new BadDataException("Monitor status timeline not found.");
258
+ }
259
+
177
260
  if (monitorStatusTimeline.isOne()) {
178
261
  throw new BadDataException(
179
262
  "Cannot delete the only status timeline. Monitor should have at least one status timeline.",
180
263
  );
181
264
  }
182
265
 
183
- // adjust times of other timeline events. get the state before this status timeline.
184
-
185
- if (monitorStatusTimelineToBeDeleted?.startsAt) {
186
- const beforeState: MonitorStatusTimeline | null =
187
- await this.findOneBy({
188
- query: {
189
- monitorId: monitorId,
190
- startsAt: QueryHelper.lessThan(
191
- monitorStatusTimelineToBeDeleted?.startsAt,
192
- ),
193
- },
194
- sort: {
195
- createdAt: SortOrder.Descending,
196
- },
197
- props: {
198
- isRoot: true,
199
- },
200
- select: {
201
- _id: true,
202
- startsAt: true,
203
- },
204
- });
205
-
206
- if (beforeState) {
207
- const afterState: MonitorStatusTimeline | null =
208
- await this.findOneBy({
209
- query: {
210
- monitorId: monitorId,
211
- startsAt: QueryHelper.greaterThan(
212
- monitorStatusTimelineToBeDeleted?.startsAt,
213
- ),
214
- },
215
- sort: {
216
- createdAt: SortOrder.Ascending,
217
- },
218
- props: {
219
- isRoot: true,
220
- },
221
- select: {
222
- _id: true,
223
- startsAt: true,
224
- },
225
- });
226
-
227
- if (!afterState) {
228
- // if there's nothing after then end date of before state is null.
229
-
230
- await this.updateOneById({
231
- id: beforeState.id!,
232
- data: {
233
- endsAt: null as any,
234
- },
235
- props: {
236
- isRoot: true,
237
- },
238
- });
239
- } else {
240
- // if there's something after then end date of before state is start date of after state.
241
-
242
- await this.updateOneById({
243
- id: beforeState.id!,
244
- data: {
245
- endsAt: afterState.startsAt!,
246
- },
247
- props: {
248
- isRoot: true,
249
- },
250
- });
251
- }
252
- }
266
+ // There are three cases.
267
+ // 1. This is the first status.
268
+ // 2. This is the last status.
269
+ // 3. This is in the middle.
270
+
271
+ const stateBeforeThis: MonitorStatusTimeline | null =
272
+ await this.findOneBy({
273
+ query: {
274
+ _id: QueryHelper.notEquals(deleteBy.query._id as string),
275
+ monitorId: monitorId,
276
+ startsAt: QueryHelper.lessThanEqualTo(
277
+ monitorStatusTimelineToBeDeleted.startsAt!,
278
+ ),
279
+ },
280
+ sort: {
281
+ startsAt: SortOrder.Descending,
282
+ },
283
+ props: {
284
+ isRoot: true,
285
+ },
286
+ select: {
287
+ monitorStatusId: true,
288
+ startsAt: true,
289
+ endsAt: true,
290
+ },
291
+ });
292
+
293
+ const stateAfterThis: MonitorStatusTimeline | null =
294
+ await this.findOneBy({
295
+ query: {
296
+ monitorId: monitorId,
297
+ startsAt: QueryHelper.greaterThan(
298
+ monitorStatusTimelineToBeDeleted.startsAt!,
299
+ ),
300
+ },
301
+ sort: {
302
+ startsAt: SortOrder.Ascending,
303
+ },
304
+ props: {
305
+ isRoot: true,
306
+ },
307
+ select: {
308
+ monitorStatusId: true,
309
+ startsAt: true,
310
+ endsAt: true,
311
+ },
312
+ });
313
+
314
+ if (!stateBeforeThis) {
315
+ // This is the first status, no need to update previous status.
316
+ logger.debug("This is the first status.");
317
+ } else if (!stateAfterThis) {
318
+ // This is the last status.
319
+ // Update the previous status to end at the start of this status.
320
+ await this.updateOneById({
321
+ id: stateBeforeThis.id!,
322
+ data: {
323
+ endsAt: monitorStatusTimelineToBeDeleted.endsAt!,
324
+ },
325
+ props: {
326
+ isRoot: true,
327
+ },
328
+ });
329
+ logger.debug("This is the last status.");
330
+ } else {
331
+ // This status is in the middle.
332
+ // Update the previous status to end at the start of this status.
333
+ await this.updateOneById({
334
+ id: stateBeforeThis.id!,
335
+ data: {
336
+ endsAt: stateAfterThis.startsAt!,
337
+ },
338
+ props: {
339
+ isRoot: true,
340
+ },
341
+ });
342
+
343
+ // Update the next status to start at the end of this status.
344
+ await this.updateOneById({
345
+ id: stateAfterThis.id!,
346
+ data: {
347
+ startsAt: monitorStatusTimelineToBeDeleted.startsAt!,
348
+ },
349
+ props: {
350
+ isRoot: true,
351
+ },
352
+ });
353
+ logger.debug("This status is in the middle.");
253
354
  }
254
355
  }
255
356
 
@@ -274,7 +375,7 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
274
375
  monitorId: monitorId,
275
376
  },
276
377
  sort: {
277
- createdAt: SortOrder.Descending,
378
+ startsAt: SortOrder.Descending,
278
379
  },
279
380
  props: {
280
381
  isRoot: true,