@oneuptime/common 10.4.13 → 10.4.15
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/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +49 -0
- package/Models/AnalyticsModels/AuditLog.ts +8 -0
- package/Models/AnalyticsModels/ExceptionInstance.ts +1 -0
- package/Models/AnalyticsModels/Log.ts +1 -0
- package/Models/AnalyticsModels/Metric.ts +10 -0
- package/Models/AnalyticsModels/MonitorLog.ts +1 -0
- package/Models/AnalyticsModels/Profile.ts +1 -0
- package/Models/AnalyticsModels/ProfileSample.ts +1 -0
- package/Models/AnalyticsModels/Span.ts +1 -0
- package/Models/DatabaseModels/Alert.ts +2 -0
- package/Models/DatabaseModels/AlertCustomField.ts +37 -0
- package/Models/DatabaseModels/AlertFeed.ts +1 -0
- package/Models/DatabaseModels/CallLog.ts +2 -0
- package/Models/DatabaseModels/DockerHost.ts +34 -0
- package/Models/DatabaseModels/EmailLog.ts +2 -0
- package/Models/DatabaseModels/Host.ts +34 -0
- package/Models/DatabaseModels/Incident.ts +1 -0
- package/Models/DatabaseModels/IncidentCustomField.ts +37 -0
- package/Models/DatabaseModels/IncidentFeed.ts +1 -0
- package/Models/DatabaseModels/IncidentMember.ts +9 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +34 -0
- package/Models/DatabaseModels/MonitorCustomField.ts +37 -0
- package/Models/DatabaseModels/MonitorFeed.ts +1 -0
- package/Models/DatabaseModels/MonitorProbe.ts +1 -0
- package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +37 -0
- package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +3 -0
- package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +37 -0
- package/Models/DatabaseModels/SmsLog.ts +2 -0
- package/Models/DatabaseModels/StatusPageCustomField.ts +37 -0
- package/Models/DatabaseModels/StatusPageSubscriber.ts +2 -0
- package/Models/DatabaseModels/TableView.ts +40 -0
- package/Models/DatabaseModels/TeamMemberCustomField.ts +37 -0
- package/Models/DatabaseModels/TelemetryException.ts +2 -0
- package/Models/DatabaseModels/UserOnCallLog.ts +1 -0
- package/Models/DatabaseModels/WorkflowLog.ts +1 -0
- package/Server/API/BaseAnalyticsAPI.ts +128 -20
- package/Server/API/MetricAPI.ts +5 -138
- package/Server/API/ProjectAPI.ts +52 -15
- package/Server/API/StatusAPI.ts +103 -7
- package/Server/EnvironmentConfig.ts +69 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +26 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.ts +160 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.ts +13 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.ts +34 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Infrastructure/PostgresDatabase.ts +2 -5
- package/Server/Middleware/ProjectAuthorization.ts +31 -53
- package/Server/Middleware/UserAuthorization.ts +106 -64
- package/Server/Services/AccessTokenService.ts +1 -1
- package/Server/Services/AnalyticsDatabaseService.ts +24 -4
- package/Server/Services/ApiKeyService.ts +100 -1
- package/Server/Services/DockerHostService.ts +5 -0
- package/Server/Services/HostService.ts +6 -0
- package/Server/Services/KubernetesClusterService.ts +33 -10
- package/Server/Services/MetricService.ts +113 -0
- package/Server/Services/MonitorService.ts +10 -3
- package/Server/Services/ProjectService.ts +93 -2
- package/Server/Services/TeamMemberService.ts +36 -0
- package/Server/Services/UserService.ts +38 -0
- package/Server/Utils/Response.ts +4 -1
- package/Server/Utils/UserPermission/UserPermission.ts +17 -1
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +2 -2
- package/Types/API/HTTPResponse.ts +16 -0
- package/Types/BaseDatabase/ListResult.ts +6 -0
- package/Types/CustomField/CustomFieldType.ts +2 -0
- package/Types/Date.ts +9 -1
- package/Types/ListData.ts +14 -0
- package/Types/Monitor/DnsMonitor/DnsMonitorResponse.ts +3 -0
- package/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.ts +5 -0
- package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +4 -0
- package/Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse.ts +4 -0
- package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +3 -0
- package/Types/Probe/ProbeAttempt.ts +9 -0
- package/Types/Probe/ProbeMonitorResponse.ts +3 -0
- package/UI/Components/BulkUpdate/BulkOwnerActions.tsx +504 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +64 -54
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +38 -0
- package/UI/Components/CustomFields/DropdownOptionsInput.tsx +150 -0
- package/UI/Components/Detail/Detail.tsx +78 -11
- package/UI/Components/List/List.tsx +6 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +74 -2
- package/UI/Components/ModelTable/TableView.tsx +70 -30
- package/UI/Components/Pagination/Pagination.tsx +75 -33
- package/UI/Components/Table/Table.tsx +6 -0
- package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +33 -0
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/AuditLog.js +8 -0
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +1 -0
- package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Log.js +1 -0
- package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Metric.js +10 -0
- package/build/dist/Models/AnalyticsModels/Metric.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MonitorLog.js +1 -0
- package/build/dist/Models/AnalyticsModels/MonitorLog.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Profile.js +1 -0
- package/build/dist/Models/AnalyticsModels/Profile.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/ProfileSample.js +1 -0
- package/build/dist/Models/AnalyticsModels/ProfileSample.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Span.js +1 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Alert.js +3 -1
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertCustomField.js +38 -0
- package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CallLog.js +4 -1
- package/build/dist/Models/DatabaseModels/CallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +35 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EmailLog.js +4 -1
- package/build/dist/Models/DatabaseModels/EmailLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +35 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +2 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js +38 -0
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -1
- package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentMember.js +11 -1
- package/build/dist/Models/DatabaseModels/IncidentMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +35 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorCustomField.js +38 -0
- package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorFeed.js +2 -1
- package/build/dist/Models/DatabaseModels/MonitorFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorProbe.js +2 -0
- package/build/dist/Models/DatabaseModels/MonitorProbe.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +38 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +3 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +38 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/SmsLog.js +4 -1
- package/build/dist/Models/DatabaseModels/SmsLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +38 -0
- package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +4 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TableView.js +40 -0
- package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +38 -0
- package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +3 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowLog.js +2 -1
- package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js +105 -18
- package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
- package/build/dist/Server/API/MetricAPI.js +5 -113
- package/build/dist/Server/API/MetricAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +42 -14
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/StatusAPI.js +75 -8
- package/build/dist/Server/API/StatusAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +41 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +20 -2
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.js +63 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js +27 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js +28 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/PostgresDatabase.js +2 -2
- package/build/dist/Server/Infrastructure/PostgresDatabase.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +21 -39
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +83 -50
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AccessTokenService.js +1 -1
- package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +22 -3
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyService.js +86 -0
- package/build/dist/Server/Services/ApiKeyService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +5 -1
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +5 -1
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +21 -11
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +89 -0
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +8 -3
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +84 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +24 -0
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +36 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +6 -5
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/UserPermission/UserPermission.js +13 -1
- package/build/dist/Server/Utils/UserPermission/UserPermission.js.map +1 -1
- package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js +2 -2
- package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js.map +1 -1
- package/build/dist/Types/API/HTTPResponse.js +15 -0
- package/build/dist/Types/API/HTTPResponse.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldType.js +2 -0
- package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
- package/build/dist/Types/Date.js +10 -1
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/ListData.js +4 -0
- package/build/dist/Types/ListData.js.map +1 -1
- package/build/dist/Types/Probe/ProbeAttempt.js +2 -0
- package/build/dist/Types/Probe/ProbeAttempt.js.map +1 -0
- package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js +376 -0
- package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js.map +1 -0
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +32 -25
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +32 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js +84 -0
- package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js.map +1 -0
- package/build/dist/UI/Components/Detail/Detail.js +34 -3
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +1 -1
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +45 -5
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js +40 -19
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/Pagination/Pagination.js +62 -36
- package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +1 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -0
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
- package/package.json +1 -1
package/Server/API/StatusAPI.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import BadRequestException from "../../Types/Exception/BadRequestException";
|
|
2
|
+
import InMemoryTTLCache from "../Infrastructure/InMemoryTTLCache";
|
|
2
3
|
import LocalCache from "../Infrastructure/LocalCache";
|
|
3
4
|
import Express, {
|
|
4
5
|
ExpressRequest,
|
|
@@ -20,7 +21,93 @@ export interface StatusAPIOptions {
|
|
|
20
21
|
databaseCheck?: (() => Promise<void>) | undefined;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Result of a recently executed health check, cached for HEALTH_CHECK_CACHE_TTL_MS.
|
|
26
|
+
* We cache both success AND failure: caching failure protects an already
|
|
27
|
+
* unhealthy backend from being hammered by retry traffic during an outage. The
|
|
28
|
+
* 5s TTL is short enough that k8s probe semantics (default 10s interval,
|
|
29
|
+
* failureThreshold 3 → ~30s to unready) are essentially unchanged.
|
|
30
|
+
*/
|
|
31
|
+
type CachedHealthCheckResult = { ok: true } | { ok: false; error: Error };
|
|
32
|
+
|
|
23
33
|
export default class StatusAPI {
|
|
34
|
+
/**
|
|
35
|
+
* Cache of recent health check results, keyed by check name. Each entry
|
|
36
|
+
* lives for HEALTH_CHECK_CACHE_TTL_MS. Bounded to a small max size — there
|
|
37
|
+
* are only ~5 distinct check names in this API.
|
|
38
|
+
*/
|
|
39
|
+
private static checkResultCache: InMemoryTTLCache<CachedHealthCheckResult> =
|
|
40
|
+
new InMemoryTTLCache<CachedHealthCheckResult>(64);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* In-flight check promises keyed by check name. When a cache miss occurs
|
|
44
|
+
* and multiple concurrent requests arrive, they all attach to the same
|
|
45
|
+
* promise instead of each triggering their own DB query. The entry is
|
|
46
|
+
* cleared as soon as the check settles.
|
|
47
|
+
*/
|
|
48
|
+
private static inflightChecks: Map<string, Promise<void>> = new Map();
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Cache TTL for health-check results. Chosen so that:
|
|
52
|
+
* - Two-thirds of typical k8s probes (default periodSeconds=10) hit
|
|
53
|
+
* the cache, removing constant DB load from liveness/readiness traffic.
|
|
54
|
+
* - Time-to-detect for a failing dependency only grows by ≤5s, which is
|
|
55
|
+
* well within the failureThreshold window k8s probes already tolerate.
|
|
56
|
+
*/
|
|
57
|
+
private static readonly HEALTH_CHECK_CACHE_TTL_MS: number = 5000;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Runs `checkFn` with two layers of protection:
|
|
61
|
+
* 1. TTL cache — if the same check ran in the last HEALTH_CHECK_CACHE_TTL_MS
|
|
62
|
+
* ms, reuse its result (success or failure) without re-running.
|
|
63
|
+
* 2. Single-flight — if a check is already in flight, concurrent callers
|
|
64
|
+
* await the same promise instead of starting their own.
|
|
65
|
+
*
|
|
66
|
+
* On cache hit this is effectively free; on cache miss we run the check
|
|
67
|
+
* exactly once regardless of how many requests arrived concurrently.
|
|
68
|
+
*/
|
|
69
|
+
private static async runCachedCheck(
|
|
70
|
+
checkName: string,
|
|
71
|
+
checkFn: () => Promise<void>,
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
const cached: CachedHealthCheckResult | undefined =
|
|
74
|
+
this.checkResultCache.get(checkName);
|
|
75
|
+
if (cached) {
|
|
76
|
+
if (cached.ok) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
throw cached.error;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let inflight: Promise<void> | undefined =
|
|
83
|
+
this.inflightChecks.get(checkName);
|
|
84
|
+
if (!inflight) {
|
|
85
|
+
inflight = (async (): Promise<void> => {
|
|
86
|
+
try {
|
|
87
|
+
await checkFn();
|
|
88
|
+
this.checkResultCache.set(
|
|
89
|
+
checkName,
|
|
90
|
+
{ ok: true },
|
|
91
|
+
this.HEALTH_CHECK_CACHE_TTL_MS,
|
|
92
|
+
);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
const error: Error = e instanceof Error ? e : new Error(String(e));
|
|
95
|
+
this.checkResultCache.set(
|
|
96
|
+
checkName,
|
|
97
|
+
{ ok: false, error },
|
|
98
|
+
this.HEALTH_CHECK_CACHE_TTL_MS,
|
|
99
|
+
);
|
|
100
|
+
throw error;
|
|
101
|
+
} finally {
|
|
102
|
+
this.inflightChecks.delete(checkName);
|
|
103
|
+
}
|
|
104
|
+
})();
|
|
105
|
+
this.inflightChecks.set(checkName, inflight);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
await inflight;
|
|
109
|
+
}
|
|
110
|
+
|
|
24
111
|
@CaptureSpan()
|
|
25
112
|
public static init(options: StatusAPIOptions): ExpressRouter {
|
|
26
113
|
const statusCheckSuccessCounter: TelemetryCounter = Telemetry.getCounter({
|
|
@@ -127,8 +214,11 @@ export default class StatusAPI {
|
|
|
127
214
|
res: ExpressResponse,
|
|
128
215
|
): Promise<void> {
|
|
129
216
|
try {
|
|
130
|
-
|
|
131
|
-
|
|
217
|
+
/*
|
|
218
|
+
* Cached for HEALTH_CHECK_CACHE_TTL_MS so k8s probe traffic does not
|
|
219
|
+
* hammer the underlying check on every request.
|
|
220
|
+
*/
|
|
221
|
+
await this.runCachedCheck("ready", options.readyCheck);
|
|
132
222
|
logger.info("Ready check: ok", getLogAttributesFromRequest(req as any));
|
|
133
223
|
stausReadySuccess.add(1);
|
|
134
224
|
|
|
@@ -160,8 +250,8 @@ export default class StatusAPI {
|
|
|
160
250
|
res: ExpressResponse,
|
|
161
251
|
): Promise<void> {
|
|
162
252
|
try {
|
|
163
|
-
|
|
164
|
-
await options.liveCheck
|
|
253
|
+
// Cached for HEALTH_CHECK_CACHE_TTL_MS — see runCachedCheck for rationale.
|
|
254
|
+
await this.runCachedCheck("live", options.liveCheck);
|
|
165
255
|
logger.info("Live check: ok", getLogAttributesFromRequest(req as any));
|
|
166
256
|
stausLiveSuccess.add(1);
|
|
167
257
|
|
|
@@ -195,7 +285,8 @@ export default class StatusAPI {
|
|
|
195
285
|
getLogAttributesFromRequest(req as any),
|
|
196
286
|
);
|
|
197
287
|
if (options.globalCacheCheck) {
|
|
198
|
-
|
|
288
|
+
// Cached — see runCachedCheck for rationale.
|
|
289
|
+
await this.runCachedCheck("global-cache", options.globalCacheCheck);
|
|
199
290
|
} else {
|
|
200
291
|
throw new BadRequestException("Global cache check not implemented");
|
|
201
292
|
}
|
|
@@ -230,7 +321,11 @@ export default class StatusAPI {
|
|
|
230
321
|
getLogAttributesFromRequest(req as any),
|
|
231
322
|
);
|
|
232
323
|
if (options.analyticsDatabaseCheck) {
|
|
233
|
-
|
|
324
|
+
// Cached — see runCachedCheck for rationale.
|
|
325
|
+
await this.runCachedCheck(
|
|
326
|
+
"analytics-database",
|
|
327
|
+
options.analyticsDatabaseCheck,
|
|
328
|
+
);
|
|
234
329
|
} else {
|
|
235
330
|
throw new BadRequestException(
|
|
236
331
|
"Analytics database check not implemented",
|
|
@@ -265,7 +360,8 @@ export default class StatusAPI {
|
|
|
265
360
|
logger.debug("Database check", getLogAttributesFromRequest(req as any));
|
|
266
361
|
|
|
267
362
|
if (options.databaseCheck) {
|
|
268
|
-
|
|
363
|
+
// Cached — see runCachedCheck for rationale.
|
|
364
|
+
await this.runCachedCheck("database", options.databaseCheck);
|
|
269
365
|
} else {
|
|
270
366
|
throw new BadRequestException("Database check not implemented");
|
|
271
367
|
}
|
|
@@ -145,6 +145,75 @@ export const ShouldDatabaseSslEnable: boolean = Boolean(
|
|
|
145
145
|
DatabaseSslCa || (DatabaseSslCert && DatabaseSslKey),
|
|
146
146
|
);
|
|
147
147
|
|
|
148
|
+
/*
|
|
149
|
+
* Postgres pool size per API/Worker node. TypeORM's default is 10 which
|
|
150
|
+
* starves the API under any meaningful load — pick a number that, when
|
|
151
|
+
* multiplied by the number of running Node processes, stays under the
|
|
152
|
+
* Postgres server's `max_connections` (default 100 on a stock cluster).
|
|
153
|
+
*/
|
|
154
|
+
export const MaxPostgresConnections: number = parseInt(
|
|
155
|
+
process.env["DATABASE_MAX_OPEN_CONNECTIONS"] || "50",
|
|
156
|
+
10,
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
/*
|
|
160
|
+
* Postgres-side statement timeout (ms). Caps the wall-clock time of any
|
|
161
|
+
* single SQL statement. Without this, a single runaway query can pin a
|
|
162
|
+
* connection forever and starve the pool.
|
|
163
|
+
*/
|
|
164
|
+
export const PostgresStatementTimeoutMs: number = parseInt(
|
|
165
|
+
process.env["DATABASE_STATEMENT_TIMEOUT_MS"] || "30000",
|
|
166
|
+
10,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
/*
|
|
170
|
+
* Node-postgres client-side query timeout (ms). Belt-and-braces for the
|
|
171
|
+
* server-side statement_timeout — fires even if the connection has gone
|
|
172
|
+
* silent or the server-side timeout doesn't kick in.
|
|
173
|
+
*/
|
|
174
|
+
export const PostgresQueryTimeoutMs: number = parseInt(
|
|
175
|
+
process.env["DATABASE_QUERY_TIMEOUT_MS"] || "30000",
|
|
176
|
+
10,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
* Postgres-side idle-in-transaction timeout (ms). Kills connections that
|
|
181
|
+
* are stuck holding row locks inside a BEGIN without committing.
|
|
182
|
+
*/
|
|
183
|
+
export const PostgresIdleInTransactionTimeoutMs: number = parseInt(
|
|
184
|
+
process.env["DATABASE_IDLE_IN_TRANSACTION_TIMEOUT_MS"] || "60000",
|
|
185
|
+
10,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
/*
|
|
189
|
+
* pg-pool acquire timeout (ms). How long a query waits for a free
|
|
190
|
+
* connection before failing. Without this, requests pile up invisibly
|
|
191
|
+
* when the pool is exhausted.
|
|
192
|
+
*/
|
|
193
|
+
export const PostgresConnectionAcquireTimeoutMs: number = parseInt(
|
|
194
|
+
process.env["DATABASE_CONNECTION_TIMEOUT_MS"] || "5000",
|
|
195
|
+
10,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
/*
|
|
199
|
+
* pg-pool idle connection timeout (ms). Closes connections that have
|
|
200
|
+
* been sitting unused for this long, freeing server-side slots.
|
|
201
|
+
*/
|
|
202
|
+
export const PostgresIdleTimeoutMs: number = parseInt(
|
|
203
|
+
process.env["DATABASE_IDLE_TIMEOUT_MS"] || "30000",
|
|
204
|
+
10,
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
/*
|
|
208
|
+
* TypeORM slow-query log threshold (ms). Any query exceeding this is
|
|
209
|
+
* logged so we can find offenders in production without per-query
|
|
210
|
+
* tracing. Set to 0 to disable.
|
|
211
|
+
*/
|
|
212
|
+
export const PostgresSlowQueryLogThresholdMs: number = parseInt(
|
|
213
|
+
process.env["DATABASE_SLOW_QUERY_LOG_THRESHOLD_MS"] || "1000",
|
|
214
|
+
10,
|
|
215
|
+
);
|
|
216
|
+
|
|
148
217
|
export const EncryptionSecret: ObjectID = new ObjectID(
|
|
149
218
|
process.env["ENCRYPTION_SECRET"] || "secret",
|
|
150
219
|
);
|
|
@@ -8,6 +8,13 @@ import {
|
|
|
8
8
|
DatabaseSslCert,
|
|
9
9
|
DatabaseSslKey,
|
|
10
10
|
DatabaseUsername,
|
|
11
|
+
MaxPostgresConnections,
|
|
12
|
+
PostgresConnectionAcquireTimeoutMs,
|
|
13
|
+
PostgresIdleInTransactionTimeoutMs,
|
|
14
|
+
PostgresIdleTimeoutMs,
|
|
15
|
+
PostgresQueryTimeoutMs,
|
|
16
|
+
PostgresSlowQueryLogThresholdMs,
|
|
17
|
+
PostgresStatementTimeoutMs,
|
|
11
18
|
ShouldDatabaseSslEnable,
|
|
12
19
|
} from "../../../Server/EnvironmentConfig";
|
|
13
20
|
import Migrations from "./SchemaMigrations/Index";
|
|
@@ -35,7 +42,25 @@ const dataSourceOptions: DataSourceOptions = {
|
|
|
35
42
|
cert: DatabaseSslCert,
|
|
36
43
|
}
|
|
37
44
|
: false,
|
|
38
|
-
|
|
45
|
+
/*
|
|
46
|
+
* Anything in `extra` is forwarded to the underlying node-postgres pool
|
|
47
|
+
* and client. Pool sizing + timeouts live here because TypeORM's defaults
|
|
48
|
+
* (10 connections, no timeouts) are too small for any non-trivial load.
|
|
49
|
+
*/
|
|
50
|
+
extra: {
|
|
51
|
+
max: MaxPostgresConnections,
|
|
52
|
+
idleTimeoutMillis: PostgresIdleTimeoutMs,
|
|
53
|
+
connectionTimeoutMillis: PostgresConnectionAcquireTimeoutMs,
|
|
54
|
+
statement_timeout: PostgresStatementTimeoutMs,
|
|
55
|
+
query_timeout: PostgresQueryTimeoutMs,
|
|
56
|
+
idle_in_transaction_session_timeout: PostgresIdleInTransactionTimeoutMs,
|
|
57
|
+
},
|
|
58
|
+
/*
|
|
59
|
+
* Log any query slower than the configured threshold so we can find
|
|
60
|
+
* offenders in production. TypeORM emits these via the configured
|
|
61
|
+
* logger; the default `advanced-console` logger writes to stdout.
|
|
62
|
+
*/
|
|
63
|
+
maxQueryExecutionTime: PostgresSlowQueryLogThresholdMs,
|
|
39
64
|
synchronize: false,
|
|
40
65
|
};
|
|
41
66
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddAgentVersionToKubernetesDockerHost1779392865146
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
name = "AddAgentVersionToKubernetesDockerHost1779392865146";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "KubernetesCluster" ADD "agentVersion" character varying(100)`,
|
|
11
|
+
);
|
|
12
|
+
await queryRunner.query(
|
|
13
|
+
`ALTER TABLE "DockerHost" ADD "agentVersion" character varying(100)`,
|
|
14
|
+
);
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`ALTER TABLE "Host" ADD "agentVersion" character varying(100)`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
21
|
+
await queryRunner.query(`ALTER TABLE "Host" DROP COLUMN "agentVersion"`);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "DockerHost" DROP COLUMN "agentVersion"`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`ALTER TABLE "KubernetesCluster" DROP COLUMN "agentVersion"`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddPerformanceIndexes1779392970424 implements MigrationInterface {
|
|
4
|
+
public name: string = "AddPerformanceIndexes1779392970424";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
// Active-X badge counters on the dashboard.
|
|
8
|
+
await queryRunner.query(
|
|
9
|
+
`CREATE INDEX "IDX_d846ce00a02d1073efc07178fa" ON "Incident" ("projectId", "currentIncidentStateId") `,
|
|
10
|
+
);
|
|
11
|
+
await queryRunner.query(
|
|
12
|
+
`CREATE INDEX "IDX_0c7286dfa90fd7d8201ec6f217" ON "Alert" ("projectId", "currentAlertStateId") `,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
// Alert filtering by monitor (monitor detail page).
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`CREATE INDEX "IDX_b57071fc2f1e27430e651382ee" ON "Alert" ("monitorId") `,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// Notification log tables: filter by project + status / time range.
|
|
21
|
+
await queryRunner.query(
|
|
22
|
+
`CREATE INDEX "IDX_8a0f032f20cd845c9bb908f38c" ON "CallLog" ("projectId", "status") `,
|
|
23
|
+
);
|
|
24
|
+
await queryRunner.query(
|
|
25
|
+
`CREATE INDEX "IDX_b59ee5f702882c10066cdd1128" ON "CallLog" ("projectId", "createdAt") `,
|
|
26
|
+
);
|
|
27
|
+
await queryRunner.query(
|
|
28
|
+
`CREATE INDEX "IDX_8f4eea9e7f20eaf121625f5787" ON "EmailLog" ("projectId", "status") `,
|
|
29
|
+
);
|
|
30
|
+
await queryRunner.query(
|
|
31
|
+
`CREATE INDEX "IDX_33d38c24249a256f89001acf83" ON "EmailLog" ("projectId", "createdAt") `,
|
|
32
|
+
);
|
|
33
|
+
await queryRunner.query(
|
|
34
|
+
`CREATE INDEX "IDX_c37d2fcfcb591afb284dad27d9" ON "SmsLog" ("projectId", "status") `,
|
|
35
|
+
);
|
|
36
|
+
await queryRunner.query(
|
|
37
|
+
`CREATE INDEX "IDX_c6bbede6b3bb66781bc7c82463" ON "SmsLog" ("projectId", "createdAt") `,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Feed timelines on alert/incident/monitor detail pages.
|
|
41
|
+
await queryRunner.query(
|
|
42
|
+
`CREATE INDEX "IDX_6f97cb7c189e6339cf364a3608" ON "AlertFeed" ("alertId", "postedAt") `,
|
|
43
|
+
);
|
|
44
|
+
await queryRunner.query(
|
|
45
|
+
`CREATE INDEX "IDX_e26bf84ec503bbfb06bcde139e" ON "IncidentFeed" ("incidentId", "postedAt") `,
|
|
46
|
+
);
|
|
47
|
+
await queryRunner.query(
|
|
48
|
+
`CREATE INDEX "IDX_5771fc57305fb0f508153b53ce" ON "MonitorFeed" ("monitorId", "postedAt") `,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// Monitor probe scheduler.
|
|
52
|
+
await queryRunner.query(
|
|
53
|
+
`CREATE INDEX "IDX_4bf4109d325af5e5b5a5665bc7" ON "MonitorProbe" ("probeId", "isEnabled", "nextPingAt") `,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// On-call duty time logs (active-on-call lookups).
|
|
57
|
+
await queryRunner.query(
|
|
58
|
+
`CREATE INDEX "IDX_43da7ffeee531e9452d36a89ba" ON "OnCallDutyPolicyTimeLog" ("userId") `,
|
|
59
|
+
);
|
|
60
|
+
await queryRunner.query(
|
|
61
|
+
`CREATE INDEX "IDX_977d907fb45cbc1a2067f490af" ON "OnCallDutyPolicyTimeLog" ("startsAt") `,
|
|
62
|
+
);
|
|
63
|
+
await queryRunner.query(
|
|
64
|
+
`CREATE INDEX "IDX_002727a958120be971790fd016" ON "OnCallDutyPolicyTimeLog" ("endsAt") `,
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Telemetry exceptions dashboard.
|
|
68
|
+
await queryRunner.query(
|
|
69
|
+
`CREATE INDEX "IDX_fa102ae5073b428e514cc2ceea" ON "TelemetryException" ("occuranceCount") `,
|
|
70
|
+
);
|
|
71
|
+
await queryRunner.query(
|
|
72
|
+
`CREATE INDEX "IDX_3836772be478de8a9df86a938d" ON "TelemetryException" ("projectId", "isResolved", "isArchived") `,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Status page subscriber dedupe.
|
|
76
|
+
await queryRunner.query(
|
|
77
|
+
`CREATE INDEX "IDX_c28628545faa67976e1d462e69" ON "StatusPageSubscriber" ("statusPageId", "subscriberPhone") `,
|
|
78
|
+
);
|
|
79
|
+
await queryRunner.query(
|
|
80
|
+
`CREATE INDEX "IDX_3a2d83fc5107c639d10a7c5cc0" ON "StatusPageSubscriber" ("statusPageId", "subscriberEmail") `,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Worker sweeps.
|
|
84
|
+
await queryRunner.query(
|
|
85
|
+
`CREATE INDEX "IDX_094b044a3d6a79695ba754cdfb" ON "UserOnCallLog" ("status") `,
|
|
86
|
+
);
|
|
87
|
+
await queryRunner.query(
|
|
88
|
+
`CREATE INDEX "IDX_7a5dc4760803e57f2d0b363e6e" ON "WorkflowLog" ("workflowStatus", "createdAt") `,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
93
|
+
await queryRunner.query(
|
|
94
|
+
`DROP INDEX "public"."IDX_7a5dc4760803e57f2d0b363e6e"`,
|
|
95
|
+
);
|
|
96
|
+
await queryRunner.query(
|
|
97
|
+
`DROP INDEX "public"."IDX_094b044a3d6a79695ba754cdfb"`,
|
|
98
|
+
);
|
|
99
|
+
await queryRunner.query(
|
|
100
|
+
`DROP INDEX "public"."IDX_3a2d83fc5107c639d10a7c5cc0"`,
|
|
101
|
+
);
|
|
102
|
+
await queryRunner.query(
|
|
103
|
+
`DROP INDEX "public"."IDX_c28628545faa67976e1d462e69"`,
|
|
104
|
+
);
|
|
105
|
+
await queryRunner.query(
|
|
106
|
+
`DROP INDEX "public"."IDX_3836772be478de8a9df86a938d"`,
|
|
107
|
+
);
|
|
108
|
+
await queryRunner.query(
|
|
109
|
+
`DROP INDEX "public"."IDX_fa102ae5073b428e514cc2ceea"`,
|
|
110
|
+
);
|
|
111
|
+
await queryRunner.query(
|
|
112
|
+
`DROP INDEX "public"."IDX_002727a958120be971790fd016"`,
|
|
113
|
+
);
|
|
114
|
+
await queryRunner.query(
|
|
115
|
+
`DROP INDEX "public"."IDX_977d907fb45cbc1a2067f490af"`,
|
|
116
|
+
);
|
|
117
|
+
await queryRunner.query(
|
|
118
|
+
`DROP INDEX "public"."IDX_43da7ffeee531e9452d36a89ba"`,
|
|
119
|
+
);
|
|
120
|
+
await queryRunner.query(
|
|
121
|
+
`DROP INDEX "public"."IDX_4bf4109d325af5e5b5a5665bc7"`,
|
|
122
|
+
);
|
|
123
|
+
await queryRunner.query(
|
|
124
|
+
`DROP INDEX "public"."IDX_5771fc57305fb0f508153b53ce"`,
|
|
125
|
+
);
|
|
126
|
+
await queryRunner.query(
|
|
127
|
+
`DROP INDEX "public"."IDX_e26bf84ec503bbfb06bcde139e"`,
|
|
128
|
+
);
|
|
129
|
+
await queryRunner.query(
|
|
130
|
+
`DROP INDEX "public"."IDX_6f97cb7c189e6339cf364a3608"`,
|
|
131
|
+
);
|
|
132
|
+
await queryRunner.query(
|
|
133
|
+
`DROP INDEX "public"."IDX_c6bbede6b3bb66781bc7c82463"`,
|
|
134
|
+
);
|
|
135
|
+
await queryRunner.query(
|
|
136
|
+
`DROP INDEX "public"."IDX_c37d2fcfcb591afb284dad27d9"`,
|
|
137
|
+
);
|
|
138
|
+
await queryRunner.query(
|
|
139
|
+
`DROP INDEX "public"."IDX_33d38c24249a256f89001acf83"`,
|
|
140
|
+
);
|
|
141
|
+
await queryRunner.query(
|
|
142
|
+
`DROP INDEX "public"."IDX_8f4eea9e7f20eaf121625f5787"`,
|
|
143
|
+
);
|
|
144
|
+
await queryRunner.query(
|
|
145
|
+
`DROP INDEX "public"."IDX_b59ee5f702882c10066cdd1128"`,
|
|
146
|
+
);
|
|
147
|
+
await queryRunner.query(
|
|
148
|
+
`DROP INDEX "public"."IDX_8a0f032f20cd845c9bb908f38c"`,
|
|
149
|
+
);
|
|
150
|
+
await queryRunner.query(
|
|
151
|
+
`DROP INDEX "public"."IDX_b57071fc2f1e27430e651382ee"`,
|
|
152
|
+
);
|
|
153
|
+
await queryRunner.query(
|
|
154
|
+
`DROP INDEX "public"."IDX_0c7286dfa90fd7d8201ec6f217"`,
|
|
155
|
+
);
|
|
156
|
+
await queryRunner.query(
|
|
157
|
+
`DROP INDEX "public"."IDX_d846ce00a02d1073efc07178fa"`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddFacetsToTableView1779536271671 implements MigrationInterface {
|
|
4
|
+
public name: string = "AddFacetsToTableView1779536271671";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`ALTER TABLE "TableView" ADD "facets" jsonb`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
11
|
+
await queryRunner.query(`ALTER TABLE "TableView" DROP COLUMN "facets"`);
|
|
12
|
+
}
|
|
13
|
+
}
|
package/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Adds an index on `IncidentMember.isMemberNotified`. The
|
|
5
|
+
* `IncidentMembers/SendMemberAddedNotification` cron polls
|
|
6
|
+
* `WHERE isMemberNotified = false` every minute; without the
|
|
7
|
+
* index that's a full table scan that scales with every
|
|
8
|
+
* incident-member assignment ever made.
|
|
9
|
+
*
|
|
10
|
+
* The autogenerated diff also picked up unrelated drift between
|
|
11
|
+
* the local dev database and the current entity models (drops
|
|
12
|
+
* of `User.themePreference`, `StatusPage.showGridView`,
|
|
13
|
+
* `StatusPageResource.statusPageGridColumnId`, and ALTER COLUMN
|
|
14
|
+
* default changes on `OnCallDutyPolicyScheduleLayer`). Those
|
|
15
|
+
* changes belong to other branches and must not run here — they
|
|
16
|
+
* were stripped to keep this migration tightly scoped.
|
|
17
|
+
*/
|
|
18
|
+
export class AddIsMemberNotifiedIndex1779540427366
|
|
19
|
+
implements MigrationInterface
|
|
20
|
+
{
|
|
21
|
+
public name: string = "AddIsMemberNotifiedIndex1779540427366";
|
|
22
|
+
|
|
23
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
24
|
+
await queryRunner.query(
|
|
25
|
+
`CREATE INDEX "IDX_0c2358ce5ea46732d76c4cbb26" ON "IncidentMember" ("isMemberNotified") `,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
30
|
+
await queryRunner.query(
|
|
31
|
+
`DROP INDEX "public"."IDX_0c2358ce5ea46732d76c4cbb26"`,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddDropdownOptionsToCustomFields1779619108628
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
public name: string = "AddDropdownOptionsToCustomFields1779619108628";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "IncidentCustomField" ADD "dropdownOptions" character varying(500)`,
|
|
11
|
+
);
|
|
12
|
+
await queryRunner.query(
|
|
13
|
+
`ALTER TABLE "MonitorCustomField" ADD "dropdownOptions" character varying(500)`,
|
|
14
|
+
);
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`ALTER TABLE "OnCallDutyPolicyCustomField" ADD "dropdownOptions" character varying(500)`,
|
|
17
|
+
);
|
|
18
|
+
await queryRunner.query(
|
|
19
|
+
`ALTER TABLE "ScheduledMaintenanceCustomField" ADD "dropdownOptions" character varying(500)`,
|
|
20
|
+
);
|
|
21
|
+
await queryRunner.query(
|
|
22
|
+
`ALTER TABLE "StatusPageCustomField" ADD "dropdownOptions" character varying(500)`,
|
|
23
|
+
);
|
|
24
|
+
await queryRunner.query(
|
|
25
|
+
`ALTER TABLE "TeamMemberCustomField" ADD "dropdownOptions" character varying(500)`,
|
|
26
|
+
);
|
|
27
|
+
await queryRunner.query(
|
|
28
|
+
`ALTER TABLE "AlertCustomField" ADD "dropdownOptions" character varying(500)`,
|
|
29
|
+
);
|
|
30
|
+
await queryRunner.query(
|
|
31
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
|
32
|
+
);
|
|
33
|
+
await queryRunner.query(
|
|
34
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
39
|
+
await queryRunner.query(
|
|
40
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
|
41
|
+
);
|
|
42
|
+
await queryRunner.query(
|
|
43
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
|
44
|
+
);
|
|
45
|
+
await queryRunner.query(
|
|
46
|
+
`ALTER TABLE "AlertCustomField" DROP COLUMN "dropdownOptions"`,
|
|
47
|
+
);
|
|
48
|
+
await queryRunner.query(
|
|
49
|
+
`ALTER TABLE "TeamMemberCustomField" DROP COLUMN "dropdownOptions"`,
|
|
50
|
+
);
|
|
51
|
+
await queryRunner.query(
|
|
52
|
+
`ALTER TABLE "StatusPageCustomField" DROP COLUMN "dropdownOptions"`,
|
|
53
|
+
);
|
|
54
|
+
await queryRunner.query(
|
|
55
|
+
`ALTER TABLE "ScheduledMaintenanceCustomField" DROP COLUMN "dropdownOptions"`,
|
|
56
|
+
);
|
|
57
|
+
await queryRunner.query(
|
|
58
|
+
`ALTER TABLE "OnCallDutyPolicyCustomField" DROP COLUMN "dropdownOptions"`,
|
|
59
|
+
);
|
|
60
|
+
await queryRunner.query(
|
|
61
|
+
`ALTER TABLE "MonitorCustomField" DROP COLUMN "dropdownOptions"`,
|
|
62
|
+
);
|
|
63
|
+
await queryRunner.query(
|
|
64
|
+
`ALTER TABLE "IncidentCustomField" DROP COLUMN "dropdownOptions"`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -342,6 +342,11 @@ import { DropServiceDependencyTable1779277271302 } from "./1779277271302-DropSer
|
|
|
342
342
|
import { AddTelemetryRetentionToHostDockerKubernetes1779282769946 } from "./1779282769946-AddTelemetryRetentionToHostDockerKubernetes";
|
|
343
343
|
import { AttachKubernetesAndDockerToIncidentAndAlert1779302536475 } from "./1779302536475-AttachKubernetesAndDockerToIncidentAndAlert";
|
|
344
344
|
import { AttachServiceToIncidentAndAlert1779303924241 } from "./1779303924241-AttachServiceToIncidentAndAlert";
|
|
345
|
+
import { AddAgentVersionToKubernetesDockerHost1779392865146 } from "./1779392865146-AddAgentVersionToKubernetesDockerHost";
|
|
346
|
+
import { AddPerformanceIndexes1779392970424 } from "./1779392970424-AddPerformanceIndexes";
|
|
347
|
+
import { AddFacetsToTableView1779536271671 } from "./1779536271671-AddFacetsToTableView";
|
|
348
|
+
import { AddIsMemberNotifiedIndex1779540427366 } from "./1779540427366-AddIsMemberNotifiedIndex";
|
|
349
|
+
import { AddDropdownOptionsToCustomFields1779619108628 } from "./1779619108628-AddDropdownOptionsToCustomFields";
|
|
345
350
|
export default [
|
|
346
351
|
InitialMigration,
|
|
347
352
|
MigrationName1717678334852,
|
|
@@ -687,4 +692,9 @@ export default [
|
|
|
687
692
|
AddTelemetryRetentionToHostDockerKubernetes1779282769946,
|
|
688
693
|
AttachKubernetesAndDockerToIncidentAndAlert1779302536475,
|
|
689
694
|
AttachServiceToIncidentAndAlert1779303924241,
|
|
695
|
+
AddAgentVersionToKubernetesDockerHost1779392865146,
|
|
696
|
+
AddPerformanceIndexes1779392970424,
|
|
697
|
+
AddFacetsToTableView1779536271671,
|
|
698
|
+
AddIsMemberNotifiedIndex1779540427366,
|
|
699
|
+
AddDropdownOptionsToCustomFields1779619108628,
|
|
690
700
|
];
|
|
@@ -82,12 +82,9 @@ export default class Database {
|
|
|
82
82
|
|
|
83
83
|
@CaptureSpan()
|
|
84
84
|
public static async checkConnnectionStatus(): Promise<boolean> {
|
|
85
|
-
//
|
|
86
|
-
|
|
85
|
+
// SELECT 1 round-trips a connection without scanning any user table.
|
|
87
86
|
try {
|
|
88
|
-
const result: any = await this.dataSource?.query(
|
|
89
|
-
`SELECT COUNT(domain) FROM "AcmeChallenge"`,
|
|
90
|
-
); // this is a dummy query to check if the connection is still alive
|
|
87
|
+
const result: any = await this.dataSource?.query(`SELECT 1`);
|
|
91
88
|
|
|
92
89
|
if (!result) {
|
|
93
90
|
return false;
|