@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.
Files changed (248) hide show
  1. package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +49 -0
  2. package/Models/AnalyticsModels/AuditLog.ts +8 -0
  3. package/Models/AnalyticsModels/ExceptionInstance.ts +1 -0
  4. package/Models/AnalyticsModels/Log.ts +1 -0
  5. package/Models/AnalyticsModels/Metric.ts +10 -0
  6. package/Models/AnalyticsModels/MonitorLog.ts +1 -0
  7. package/Models/AnalyticsModels/Profile.ts +1 -0
  8. package/Models/AnalyticsModels/ProfileSample.ts +1 -0
  9. package/Models/AnalyticsModels/Span.ts +1 -0
  10. package/Models/DatabaseModels/Alert.ts +2 -0
  11. package/Models/DatabaseModels/AlertCustomField.ts +37 -0
  12. package/Models/DatabaseModels/AlertFeed.ts +1 -0
  13. package/Models/DatabaseModels/CallLog.ts +2 -0
  14. package/Models/DatabaseModels/DockerHost.ts +34 -0
  15. package/Models/DatabaseModels/EmailLog.ts +2 -0
  16. package/Models/DatabaseModels/Host.ts +34 -0
  17. package/Models/DatabaseModels/Incident.ts +1 -0
  18. package/Models/DatabaseModels/IncidentCustomField.ts +37 -0
  19. package/Models/DatabaseModels/IncidentFeed.ts +1 -0
  20. package/Models/DatabaseModels/IncidentMember.ts +9 -0
  21. package/Models/DatabaseModels/KubernetesCluster.ts +34 -0
  22. package/Models/DatabaseModels/MonitorCustomField.ts +37 -0
  23. package/Models/DatabaseModels/MonitorFeed.ts +1 -0
  24. package/Models/DatabaseModels/MonitorProbe.ts +1 -0
  25. package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +37 -0
  26. package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +3 -0
  27. package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +37 -0
  28. package/Models/DatabaseModels/SmsLog.ts +2 -0
  29. package/Models/DatabaseModels/StatusPageCustomField.ts +37 -0
  30. package/Models/DatabaseModels/StatusPageSubscriber.ts +2 -0
  31. package/Models/DatabaseModels/TableView.ts +40 -0
  32. package/Models/DatabaseModels/TeamMemberCustomField.ts +37 -0
  33. package/Models/DatabaseModels/TelemetryException.ts +2 -0
  34. package/Models/DatabaseModels/UserOnCallLog.ts +1 -0
  35. package/Models/DatabaseModels/WorkflowLog.ts +1 -0
  36. package/Server/API/BaseAnalyticsAPI.ts +128 -20
  37. package/Server/API/MetricAPI.ts +5 -138
  38. package/Server/API/ProjectAPI.ts +52 -15
  39. package/Server/API/StatusAPI.ts +103 -7
  40. package/Server/EnvironmentConfig.ts +69 -0
  41. package/Server/Infrastructure/Postgres/DataSourceOptions.ts +26 -1
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.ts +29 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.ts +160 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.ts +13 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.ts +34 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.ts +67 -0
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  48. package/Server/Infrastructure/PostgresDatabase.ts +2 -5
  49. package/Server/Middleware/ProjectAuthorization.ts +31 -53
  50. package/Server/Middleware/UserAuthorization.ts +106 -64
  51. package/Server/Services/AccessTokenService.ts +1 -1
  52. package/Server/Services/AnalyticsDatabaseService.ts +24 -4
  53. package/Server/Services/ApiKeyService.ts +100 -1
  54. package/Server/Services/DockerHostService.ts +5 -0
  55. package/Server/Services/HostService.ts +6 -0
  56. package/Server/Services/KubernetesClusterService.ts +33 -10
  57. package/Server/Services/MetricService.ts +113 -0
  58. package/Server/Services/MonitorService.ts +10 -3
  59. package/Server/Services/ProjectService.ts +93 -2
  60. package/Server/Services/TeamMemberService.ts +36 -0
  61. package/Server/Services/UserService.ts +38 -0
  62. package/Server/Utils/Response.ts +4 -1
  63. package/Server/Utils/UserPermission/UserPermission.ts +17 -1
  64. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +2 -2
  65. package/Types/API/HTTPResponse.ts +16 -0
  66. package/Types/BaseDatabase/ListResult.ts +6 -0
  67. package/Types/CustomField/CustomFieldType.ts +2 -0
  68. package/Types/Date.ts +9 -1
  69. package/Types/ListData.ts +14 -0
  70. package/Types/Monitor/DnsMonitor/DnsMonitorResponse.ts +3 -0
  71. package/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.ts +5 -0
  72. package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +4 -0
  73. package/Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse.ts +4 -0
  74. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +3 -0
  75. package/Types/Probe/ProbeAttempt.ts +9 -0
  76. package/Types/Probe/ProbeMonitorResponse.ts +3 -0
  77. package/UI/Components/BulkUpdate/BulkOwnerActions.tsx +504 -0
  78. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +64 -54
  79. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +38 -0
  80. package/UI/Components/CustomFields/DropdownOptionsInput.tsx +150 -0
  81. package/UI/Components/Detail/Detail.tsx +78 -11
  82. package/UI/Components/List/List.tsx +6 -0
  83. package/UI/Components/ModelTable/BaseModelTable.tsx +74 -2
  84. package/UI/Components/ModelTable/TableView.tsx +70 -30
  85. package/UI/Components/Pagination/Pagination.tsx +75 -33
  86. package/UI/Components/Table/Table.tsx +6 -0
  87. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
  88. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +33 -0
  89. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
  90. package/build/dist/Models/AnalyticsModels/AuditLog.js +8 -0
  91. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  92. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +1 -0
  93. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
  94. package/build/dist/Models/AnalyticsModels/Log.js +1 -0
  95. package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
  96. package/build/dist/Models/AnalyticsModels/Metric.js +10 -0
  97. package/build/dist/Models/AnalyticsModels/Metric.js.map +1 -1
  98. package/build/dist/Models/AnalyticsModels/MonitorLog.js +1 -0
  99. package/build/dist/Models/AnalyticsModels/MonitorLog.js.map +1 -1
  100. package/build/dist/Models/AnalyticsModels/Profile.js +1 -0
  101. package/build/dist/Models/AnalyticsModels/Profile.js.map +1 -1
  102. package/build/dist/Models/AnalyticsModels/ProfileSample.js +1 -0
  103. package/build/dist/Models/AnalyticsModels/ProfileSample.js.map +1 -1
  104. package/build/dist/Models/AnalyticsModels/Span.js +1 -0
  105. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  106. package/build/dist/Models/DatabaseModels/Alert.js +3 -1
  107. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  108. package/build/dist/Models/DatabaseModels/AlertCustomField.js +38 -0
  109. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
  110. package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -1
  111. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  112. package/build/dist/Models/DatabaseModels/CallLog.js +4 -1
  113. package/build/dist/Models/DatabaseModels/CallLog.js.map +1 -1
  114. package/build/dist/Models/DatabaseModels/DockerHost.js +35 -0
  115. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  116. package/build/dist/Models/DatabaseModels/EmailLog.js +4 -1
  117. package/build/dist/Models/DatabaseModels/EmailLog.js.map +1 -1
  118. package/build/dist/Models/DatabaseModels/Host.js +35 -0
  119. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  120. package/build/dist/Models/DatabaseModels/Incident.js +2 -1
  121. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  122. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +38 -0
  123. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  124. package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -1
  125. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  126. package/build/dist/Models/DatabaseModels/IncidentMember.js +11 -1
  127. package/build/dist/Models/DatabaseModels/IncidentMember.js.map +1 -1
  128. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +35 -0
  129. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  130. package/build/dist/Models/DatabaseModels/MonitorCustomField.js +38 -0
  131. package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
  132. package/build/dist/Models/DatabaseModels/MonitorFeed.js +2 -1
  133. package/build/dist/Models/DatabaseModels/MonitorFeed.js.map +1 -1
  134. package/build/dist/Models/DatabaseModels/MonitorProbe.js +2 -0
  135. package/build/dist/Models/DatabaseModels/MonitorProbe.js.map +1 -1
  136. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +38 -0
  137. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
  138. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +3 -0
  139. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
  140. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +38 -0
  141. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
  142. package/build/dist/Models/DatabaseModels/SmsLog.js +4 -1
  143. package/build/dist/Models/DatabaseModels/SmsLog.js.map +1 -1
  144. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +38 -0
  145. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
  146. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +4 -1
  147. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
  148. package/build/dist/Models/DatabaseModels/TableView.js +40 -0
  149. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
  150. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +38 -0
  151. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
  152. package/build/dist/Models/DatabaseModels/TelemetryException.js +3 -1
  153. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  154. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -0
  155. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  156. package/build/dist/Models/DatabaseModels/WorkflowLog.js +2 -1
  157. package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
  158. package/build/dist/Server/API/BaseAnalyticsAPI.js +105 -18
  159. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  160. package/build/dist/Server/API/MetricAPI.js +5 -113
  161. package/build/dist/Server/API/MetricAPI.js.map +1 -1
  162. package/build/dist/Server/API/ProjectAPI.js +42 -14
  163. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  164. package/build/dist/Server/API/StatusAPI.js +75 -8
  165. package/build/dist/Server/API/StatusAPI.js.map +1 -1
  166. package/build/dist/Server/EnvironmentConfig.js +41 -0
  167. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  168. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +20 -2
  169. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
  170. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.js +16 -0
  171. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.js.map +1 -0
  172. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.js +63 -0
  173. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.js.map +1 -0
  174. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js +12 -0
  175. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js.map +1 -0
  176. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js +27 -0
  177. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js.map +1 -0
  178. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js +28 -0
  179. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js.map +1 -0
  180. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  181. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  182. package/build/dist/Server/Infrastructure/PostgresDatabase.js +2 -2
  183. package/build/dist/Server/Infrastructure/PostgresDatabase.js.map +1 -1
  184. package/build/dist/Server/Middleware/ProjectAuthorization.js +21 -39
  185. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  186. package/build/dist/Server/Middleware/UserAuthorization.js +83 -50
  187. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  188. package/build/dist/Server/Services/AccessTokenService.js +1 -1
  189. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  190. package/build/dist/Server/Services/AnalyticsDatabaseService.js +22 -3
  191. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  192. package/build/dist/Server/Services/ApiKeyService.js +86 -0
  193. package/build/dist/Server/Services/ApiKeyService.js.map +1 -1
  194. package/build/dist/Server/Services/DockerHostService.js +5 -1
  195. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  196. package/build/dist/Server/Services/HostService.js +5 -1
  197. package/build/dist/Server/Services/HostService.js.map +1 -1
  198. package/build/dist/Server/Services/KubernetesClusterService.js +21 -11
  199. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  200. package/build/dist/Server/Services/MetricService.js +89 -0
  201. package/build/dist/Server/Services/MetricService.js.map +1 -1
  202. package/build/dist/Server/Services/MonitorService.js +8 -3
  203. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  204. package/build/dist/Server/Services/ProjectService.js +84 -2
  205. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  206. package/build/dist/Server/Services/TeamMemberService.js +24 -0
  207. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  208. package/build/dist/Server/Services/UserService.js +36 -0
  209. package/build/dist/Server/Services/UserService.js.map +1 -1
  210. package/build/dist/Server/Utils/Response.js +6 -5
  211. package/build/dist/Server/Utils/Response.js.map +1 -1
  212. package/build/dist/Server/Utils/UserPermission/UserPermission.js +13 -1
  213. package/build/dist/Server/Utils/UserPermission/UserPermission.js.map +1 -1
  214. package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js +2 -2
  215. package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js.map +1 -1
  216. package/build/dist/Types/API/HTTPResponse.js +15 -0
  217. package/build/dist/Types/API/HTTPResponse.js.map +1 -1
  218. package/build/dist/Types/CustomField/CustomFieldType.js +2 -0
  219. package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
  220. package/build/dist/Types/Date.js +10 -1
  221. package/build/dist/Types/Date.js.map +1 -1
  222. package/build/dist/Types/ListData.js +4 -0
  223. package/build/dist/Types/ListData.js.map +1 -1
  224. package/build/dist/Types/Probe/ProbeAttempt.js +2 -0
  225. package/build/dist/Types/Probe/ProbeAttempt.js.map +1 -0
  226. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js +376 -0
  227. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js.map +1 -0
  228. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +32 -25
  229. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  230. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +32 -0
  231. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  232. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js +84 -0
  233. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js.map +1 -0
  234. package/build/dist/UI/Components/Detail/Detail.js +34 -3
  235. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  236. package/build/dist/UI/Components/List/List.js +1 -1
  237. package/build/dist/UI/Components/List/List.js.map +1 -1
  238. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +45 -5
  239. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  240. package/build/dist/UI/Components/ModelTable/TableView.js +40 -19
  241. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  242. package/build/dist/UI/Components/Pagination/Pagination.js +62 -36
  243. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  244. package/build/dist/UI/Components/Table/Table.js +1 -1
  245. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  246. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -0
  247. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  248. package/package.json +1 -1
@@ -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
- logger.info("Ready check: Init", getLogAttributesFromRequest(req as any));
131
- await options.readyCheck();
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
- logger.info("Live check: Init", getLogAttributesFromRequest(req as any));
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
- await options.globalCacheCheck();
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
- await options.analyticsDatabaseCheck();
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
- await options.databaseCheck();
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
- // logging: 'all',
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
+ }
@@ -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
+ }
@@ -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
- // check popstgres connection to see if it is still alive
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;