@oneuptime/common 7.0.3822 → 7.0.3827
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.
- package/Server/Services/AlertStateTimelineService.ts +192 -86
- package/Server/Services/IncidentStateTimelineService.ts +205 -103
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +201 -101
- package/build/dist/Server/Services/AlertStateTimelineService.js +171 -72
- package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +171 -73
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +174 -80
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/package.json +2 -2
|
@@ -26,7 +26,7 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
|
|
|
26
26
|
public constructor() {
|
|
27
27
|
super(IncidentStateTimeline);
|
|
28
28
|
if (IsBillingEnabled) {
|
|
29
|
-
this.hardDeleteItemsOlderThanInDays("
|
|
29
|
+
this.hardDeleteItemsOlderThanInDays("startsAt", 120);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -91,21 +91,58 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
94
|
+
const stateBeforeThis: IncidentStateTimeline | null = await this.findOneBy({
|
|
95
|
+
query: {
|
|
96
|
+
incidentId: createBy.data.incidentId,
|
|
97
|
+
startsAt: QueryHelper.lessThanEqualTo(createBy.data.startsAt),
|
|
98
|
+
},
|
|
99
|
+
sort: {
|
|
100
|
+
startsAt: SortOrder.Descending,
|
|
101
|
+
},
|
|
102
|
+
props: {
|
|
103
|
+
isRoot: true,
|
|
104
|
+
},
|
|
105
|
+
select: {
|
|
106
|
+
incidentStateId: true,
|
|
107
|
+
startsAt: true,
|
|
108
|
+
endsAt: true,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
logger.debug("State Before this");
|
|
113
|
+
logger.debug(stateBeforeThis);
|
|
114
|
+
|
|
115
|
+
// If this is the first state, then do not notify the owner.
|
|
116
|
+
if (!stateBeforeThis) {
|
|
117
|
+
// since this is the first status, do not notify the owner.
|
|
118
|
+
createBy.data.isOwnerNotified = true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const stateAfterThis: IncidentStateTimeline | null = await this.findOneBy({
|
|
122
|
+
query: {
|
|
123
|
+
incidentId: createBy.data.incidentId,
|
|
124
|
+
startsAt: QueryHelper.greaterThan(createBy.data.startsAt),
|
|
125
|
+
},
|
|
126
|
+
sort: {
|
|
127
|
+
startsAt: SortOrder.Ascending,
|
|
128
|
+
},
|
|
129
|
+
props: {
|
|
130
|
+
isRoot: true,
|
|
131
|
+
},
|
|
132
|
+
select: {
|
|
133
|
+
incidentStateId: true,
|
|
134
|
+
startsAt: true,
|
|
135
|
+
endsAt: true,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// compute ends at. It's the start of the next status.
|
|
140
|
+
if (stateAfterThis && stateAfterThis.startsAt) {
|
|
141
|
+
createBy.data.endsAt = stateAfterThis.startsAt;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
logger.debug("State After this");
|
|
145
|
+
logger.debug(stateAfterThis);
|
|
109
146
|
|
|
110
147
|
const publicNote: string | undefined = (
|
|
111
148
|
createBy.miscDataProps as JSONObject | undefined
|
|
@@ -121,7 +158,8 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
|
|
|
121
158
|
return {
|
|
122
159
|
createBy,
|
|
123
160
|
carryForward: {
|
|
124
|
-
|
|
161
|
+
statusTimelineBeforeThisStatus: stateBeforeThis || null,
|
|
162
|
+
statusTimelineAfterThisStatus: stateAfterThis || null,
|
|
125
163
|
publicNote: publicNote,
|
|
126
164
|
},
|
|
127
165
|
};
|
|
@@ -138,33 +176,72 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
|
|
|
138
176
|
if (!createdItem.incidentStateId) {
|
|
139
177
|
throw new BadDataException("incidentStateId is null");
|
|
140
178
|
}
|
|
141
|
-
|
|
142
179
|
// update the last status as ended.
|
|
143
180
|
|
|
144
|
-
|
|
181
|
+
logger.debug("Status Timeline Before this");
|
|
182
|
+
logger.debug(onCreate.carryForward.statusTimelineBeforeThisStatus);
|
|
183
|
+
|
|
184
|
+
logger.debug("Status Timeline After this");
|
|
185
|
+
logger.debug(onCreate.carryForward.statusTimelineAfterThisStatus);
|
|
186
|
+
|
|
187
|
+
logger.debug("Created Item");
|
|
188
|
+
logger.debug(createdItem);
|
|
189
|
+
|
|
190
|
+
// now there are three cases.
|
|
191
|
+
// 1. This is the first status OR there's no status after this.
|
|
192
|
+
if (!onCreate.carryForward.statusTimelineBeforeThisStatus) {
|
|
193
|
+
// This is the first status, no need to update previous status.
|
|
194
|
+
logger.debug("This is the first status.");
|
|
195
|
+
} else if (!onCreate.carryForward.statusTimelineAfterThisStatus) {
|
|
196
|
+
// 2. This is the last status.
|
|
197
|
+
// Update the previous status to end at the start of this status.
|
|
145
198
|
await this.updateOneById({
|
|
146
|
-
id: onCreate.carryForward.
|
|
199
|
+
id: onCreate.carryForward.statusTimelineBeforeThisStatus.id!,
|
|
147
200
|
data: {
|
|
148
|
-
endsAt: createdItem.
|
|
201
|
+
endsAt: createdItem.startsAt!,
|
|
202
|
+
},
|
|
203
|
+
props: {
|
|
204
|
+
isRoot: true,
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
logger.debug("This is the last status.");
|
|
208
|
+
} else {
|
|
209
|
+
// 3. This is in the middle.
|
|
210
|
+
// Update the previous status to end at the start of this status.
|
|
211
|
+
await this.updateOneById({
|
|
212
|
+
id: onCreate.carryForward.statusTimelineBeforeThisStatus.id!,
|
|
213
|
+
data: {
|
|
214
|
+
endsAt: createdItem.startsAt!,
|
|
149
215
|
},
|
|
150
216
|
props: {
|
|
151
217
|
isRoot: true,
|
|
152
218
|
},
|
|
153
219
|
});
|
|
154
|
-
}
|
|
155
220
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
221
|
+
// Update the next status to start at the end of this status.
|
|
222
|
+
await this.updateOneById({
|
|
223
|
+
id: onCreate.carryForward.statusTimelineAfterThisStatus.id!,
|
|
224
|
+
data: {
|
|
225
|
+
startsAt: createdItem.endsAt!,
|
|
226
|
+
},
|
|
227
|
+
props: {
|
|
228
|
+
isRoot: true,
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
logger.debug("This status is in the middle.");
|
|
232
|
+
}
|
|
165
233
|
|
|
166
|
-
|
|
167
|
-
|
|
234
|
+
if (!createdItem.endsAt) {
|
|
235
|
+
await IncidentService.updateOneBy({
|
|
236
|
+
query: {
|
|
237
|
+
_id: createdItem.incidentId?.toString(),
|
|
238
|
+
},
|
|
239
|
+
data: {
|
|
240
|
+
currentIncidentStateId: createdItem.incidentStateId,
|
|
241
|
+
},
|
|
242
|
+
props: onCreate.createBy.props,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
168
245
|
|
|
169
246
|
const incidentState: IncidentState | null =
|
|
170
247
|
await IncidentStateService.findOneBy({
|
|
@@ -291,6 +368,7 @@ ${createdItem.rootCause}`,
|
|
|
291
368
|
select: {
|
|
292
369
|
incidentId: true,
|
|
293
370
|
startsAt: true,
|
|
371
|
+
endsAt: true,
|
|
294
372
|
},
|
|
295
373
|
props: {
|
|
296
374
|
isRoot: true,
|
|
@@ -310,80 +388,104 @@ ${createdItem.rootCause}`,
|
|
|
310
388
|
},
|
|
311
389
|
});
|
|
312
390
|
|
|
391
|
+
if (!incidentStateTimelineToBeDeleted) {
|
|
392
|
+
throw new BadDataException("Incident state timeline not found.");
|
|
393
|
+
}
|
|
394
|
+
|
|
313
395
|
if (incidentStateTimeline.isOne()) {
|
|
314
396
|
throw new BadDataException(
|
|
315
397
|
"Cannot delete the only state timeline. Incident should have at least one state in its timeline.",
|
|
316
398
|
);
|
|
317
399
|
}
|
|
318
400
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
401
|
+
// There are three cases.
|
|
402
|
+
// 1. This is the first state.
|
|
403
|
+
// 2. This is the last state.
|
|
404
|
+
// 3. This is in the middle.
|
|
405
|
+
|
|
406
|
+
const stateBeforeThis: IncidentStateTimeline | null =
|
|
407
|
+
await this.findOneBy({
|
|
408
|
+
query: {
|
|
409
|
+
_id: QueryHelper.notEquals(deleteBy.query._id as string),
|
|
410
|
+
incidentId: incidentId,
|
|
411
|
+
startsAt: QueryHelper.lessThanEqualTo(
|
|
412
|
+
incidentStateTimelineToBeDeleted.startsAt!,
|
|
413
|
+
),
|
|
414
|
+
},
|
|
415
|
+
sort: {
|
|
416
|
+
startsAt: SortOrder.Descending,
|
|
417
|
+
},
|
|
418
|
+
props: {
|
|
419
|
+
isRoot: true,
|
|
420
|
+
},
|
|
421
|
+
select: {
|
|
422
|
+
incidentStateId: true,
|
|
423
|
+
startsAt: true,
|
|
424
|
+
endsAt: true,
|
|
425
|
+
},
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
const stateAfterThis: IncidentStateTimeline | null =
|
|
429
|
+
await this.findOneBy({
|
|
430
|
+
query: {
|
|
431
|
+
incidentId: incidentId,
|
|
432
|
+
startsAt: QueryHelper.greaterThan(
|
|
433
|
+
incidentStateTimelineToBeDeleted.startsAt!,
|
|
434
|
+
),
|
|
435
|
+
},
|
|
436
|
+
sort: {
|
|
437
|
+
startsAt: SortOrder.Ascending,
|
|
438
|
+
},
|
|
439
|
+
props: {
|
|
440
|
+
isRoot: true,
|
|
441
|
+
},
|
|
442
|
+
select: {
|
|
443
|
+
incidentStateId: true,
|
|
444
|
+
startsAt: true,
|
|
445
|
+
endsAt: true,
|
|
446
|
+
},
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
if (!stateBeforeThis) {
|
|
450
|
+
// This is the first state, no need to update previous state.
|
|
451
|
+
logger.debug("This is the first state.");
|
|
452
|
+
} else if (!stateAfterThis) {
|
|
453
|
+
// This is the last state.
|
|
454
|
+
// Update the previous state to end at the end of this state.
|
|
455
|
+
await this.updateOneById({
|
|
456
|
+
id: stateBeforeThis.id!,
|
|
457
|
+
data: {
|
|
458
|
+
endsAt: incidentStateTimelineToBeDeleted.endsAt!,
|
|
459
|
+
},
|
|
460
|
+
props: {
|
|
461
|
+
isRoot: true,
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
logger.debug("This is the last state.");
|
|
465
|
+
} else {
|
|
466
|
+
// This state is in the middle.
|
|
467
|
+
// Update the previous state to end at the start of the next state.
|
|
468
|
+
await this.updateOneById({
|
|
469
|
+
id: stateBeforeThis.id!,
|
|
470
|
+
data: {
|
|
471
|
+
endsAt: stateAfterThis.startsAt!,
|
|
472
|
+
},
|
|
473
|
+
props: {
|
|
474
|
+
isRoot: true,
|
|
475
|
+
},
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// Update the next state to start at the start of this state.
|
|
479
|
+
await this.updateOneById({
|
|
480
|
+
id: stateAfterThis.id!,
|
|
481
|
+
data: {
|
|
482
|
+
startsAt: incidentStateTimelineToBeDeleted.startsAt!,
|
|
483
|
+
},
|
|
484
|
+
props: {
|
|
485
|
+
isRoot: true,
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
logger.debug("This state is in the middle.");
|
|
387
489
|
}
|
|
388
490
|
}
|
|
389
491
|
|
|
@@ -401,14 +503,14 @@ ${createdItem.rootCause}`,
|
|
|
401
503
|
// this is incidentId.
|
|
402
504
|
const incidentId: ObjectID = onDelete.carryForward as ObjectID;
|
|
403
505
|
|
|
404
|
-
// get last status of this
|
|
506
|
+
// get last status of this incident.
|
|
405
507
|
const incidentStateTimeline: IncidentStateTimeline | null =
|
|
406
508
|
await this.findOneBy({
|
|
407
509
|
query: {
|
|
408
510
|
incidentId: incidentId,
|
|
409
511
|
},
|
|
410
512
|
sort: {
|
|
411
|
-
|
|
513
|
+
startsAt: SortOrder.Descending,
|
|
412
514
|
},
|
|
413
515
|
props: {
|
|
414
516
|
isRoot: true,
|