@oneuptime/common 11.3.2 → 11.3.3

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 (34) hide show
  1. package/Server/Infrastructure/ClickhouseConfig.ts +21 -0
  2. package/Server/Infrastructure/ClickhouseDatabase.ts +12 -0
  3. package/Server/Services/AnalyticsDatabaseService.ts +79 -4
  4. package/Tests/UI/Components/Pill.test.tsx +3 -1
  5. package/UI/Components/EditionLabel/EditionLabel.tsx +6 -1
  6. package/UI/Components/Footer/Footer.tsx +1 -1
  7. package/UI/Components/Icon/Icon.tsx +13 -1
  8. package/UI/Components/Image/Image.tsx +6 -1
  9. package/UI/Components/Link/Link.tsx +22 -0
  10. package/UI/Components/MasterPage/MasterPage.tsx +30 -1
  11. package/UI/Components/Page/Page.tsx +29 -2
  12. package/UI/Components/Pagination/Pagination.tsx +110 -180
  13. package/build/dist/Server/Infrastructure/ClickhouseConfig.js +17 -0
  14. package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
  15. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +10 -1
  16. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
  17. package/build/dist/Server/Services/AnalyticsDatabaseService.js +59 -8
  18. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  19. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +1 -1
  20. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  21. package/build/dist/UI/Components/Footer/Footer.js +1 -1
  22. package/build/dist/UI/Components/Icon/Icon.js +2 -2
  23. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  24. package/build/dist/UI/Components/Image/Image.js +8 -1
  25. package/build/dist/UI/Components/Image/Image.js.map +1 -1
  26. package/build/dist/UI/Components/Link/Link.js +9 -0
  27. package/build/dist/UI/Components/Link/Link.js.map +1 -1
  28. package/build/dist/UI/Components/MasterPage/MasterPage.js +2 -1
  29. package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
  30. package/build/dist/UI/Components/Page/Page.js +24 -1
  31. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  32. package/build/dist/UI/Components/Pagination/Pagination.js +44 -94
  33. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  34. package/package.json +1 -1
@@ -133,116 +133,81 @@ const Pagination: FunctionComponent<ComponentProps> = (
133
133
  />
134
134
  </div>
135
135
 
136
- <ul className="py-3" role="list">
137
- <li
138
- role="button"
139
- tabIndex={isPreviousDisabled ? -1 : 0}
140
- aria-disabled={isPreviousDisabled}
141
- aria-label="Go to previous page"
142
- onClick={() => {
143
- let currentPageNumber: number = props.currentPageNumber;
144
-
145
- if (typeof currentPageNumber === "string") {
146
- currentPageNumber = parseInt(currentPageNumber);
147
- }
148
-
149
- if (props.onNavigateToPage && !isPreviousDisabled) {
150
- props.onNavigateToPage(
151
- currentPageNumber - 1,
152
- props.itemsOnPage,
153
- );
154
- }
155
- }}
156
- onKeyDown={(e: React.KeyboardEvent) => {
157
- if (
158
- (e.key === "Enter" || e.key === " ") &&
159
- !isPreviousDisabled
160
- ) {
161
- e.preventDefault();
136
+ <ul className="flex py-3" role="list">
137
+ <li className="flex">
138
+ <button
139
+ type="button"
140
+ disabled={isPreviousDisabled}
141
+ aria-label="Go to previous page"
142
+ onClick={() => {
162
143
  let currentPageNumber: number = props.currentPageNumber;
144
+
163
145
  if (typeof currentPageNumber === "string") {
164
146
  currentPageNumber = parseInt(currentPageNumber);
165
147
  }
166
- if (props.onNavigateToPage) {
148
+
149
+ if (props.onNavigateToPage && !isPreviousDisabled) {
167
150
  props.onNavigateToPage(
168
151
  currentPageNumber - 1,
169
152
  props.itemsOnPage,
170
153
  );
171
154
  }
172
- }
173
- }}
174
- className={` inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 ${
175
- isPreviousDisabled
176
- ? "bg-gray-100"
177
- : "hover:bg-gray-50 cursor-pointer"
178
- }`}
179
- >
180
- <span className="page-link">Previous</span>
155
+ }}
156
+ className={` inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500 ${
157
+ isPreviousDisabled
158
+ ? "bg-gray-100 cursor-not-allowed"
159
+ : "hover:bg-gray-50 cursor-pointer"
160
+ }`}
161
+ >
162
+ <span className="page-link">Previous</span>
163
+ </button>
181
164
  </li>
182
- <li
183
- role="button"
184
- tabIndex={isCurrentPageButtonDisabled ? -1 : 0}
185
- aria-current="page"
186
- aria-label={`Page ${props.currentPageNumber}, click to change page`}
187
- data-testid="current-page-link"
188
- className={` z-10 inline-flex items-center border border-x-0 border-gray-300 hover:bg-gray-50 px-4 py-2 text-sm font-medium text-text-600 cursor-pointer ${
189
- isCurrentPageButtonDisabled ? "bg-gray-100" : ""
190
- }`}
191
- onClick={() => {
192
- if (!isHasMoreMode) {
193
- setShowPaginationModel(true);
194
- }
195
- }}
196
- onKeyDown={(e: React.KeyboardEvent) => {
197
- if ((e.key === "Enter" || e.key === " ") && !isHasMoreMode) {
198
- e.preventDefault();
199
- setShowPaginationModel(true);
200
- }
201
- }}
202
- >
203
- <span>{props.currentPageNumber}</span>
165
+ <li className="flex">
166
+ <button
167
+ type="button"
168
+ disabled={isCurrentPageButtonDisabled}
169
+ aria-current="page"
170
+ aria-label={`Page ${props.currentPageNumber}, current page. Select to jump to another page.`}
171
+ data-testid="current-page-link"
172
+ className={` z-10 inline-flex items-center border border-x-0 border-gray-300 hover:bg-gray-50 px-4 py-2 text-sm font-medium text-text-600 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500 ${
173
+ isCurrentPageButtonDisabled ? "bg-gray-100" : ""
174
+ }`}
175
+ onClick={() => {
176
+ if (!isHasMoreMode) {
177
+ setShowPaginationModel(true);
178
+ }
179
+ }}
180
+ >
181
+ <span>{props.currentPageNumber}</span>
182
+ </button>
204
183
  </li>
205
- <li
206
- role="button"
207
- tabIndex={isNextDisabled ? -1 : 0}
208
- aria-disabled={isNextDisabled}
209
- aria-label="Go to next page"
210
- onClick={() => {
211
- let currentPageNumber: number = props.currentPageNumber;
212
-
213
- if (typeof currentPageNumber === "string") {
214
- currentPageNumber = parseInt(currentPageNumber);
215
- }
216
-
217
- if (props.onNavigateToPage && !isNextDisabled) {
218
- props.onNavigateToPage(
219
- currentPageNumber + 1,
220
- props.itemsOnPage,
221
- );
222
- }
223
- }}
224
- onKeyDown={(e: React.KeyboardEvent) => {
225
- if ((e.key === "Enter" || e.key === " ") && !isNextDisabled) {
226
- e.preventDefault();
184
+ <li className="flex">
185
+ <button
186
+ type="button"
187
+ disabled={isNextDisabled}
188
+ aria-label="Go to next page"
189
+ onClick={() => {
227
190
  let currentPageNumber: number = props.currentPageNumber;
191
+
228
192
  if (typeof currentPageNumber === "string") {
229
193
  currentPageNumber = parseInt(currentPageNumber);
230
194
  }
231
- if (props.onNavigateToPage) {
195
+
196
+ if (props.onNavigateToPage && !isNextDisabled) {
232
197
  props.onNavigateToPage(
233
198
  currentPageNumber + 1,
234
199
  props.itemsOnPage,
235
200
  );
236
201
  }
237
- }
238
- }}
239
- className={` inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 ${
240
- isNextDisabled
241
- ? "bg-gray-100"
242
- : " hover:bg-gray-50 cursor-pointer"
243
- }`}
244
- >
245
- <span>Next</span>
202
+ }}
203
+ className={` inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500 ${
204
+ isNextDisabled
205
+ ? "bg-gray-100 cursor-not-allowed"
206
+ : " hover:bg-gray-50 cursor-pointer"
207
+ }`}
208
+ >
209
+ <span>Next</span>
210
+ </button>
246
211
  </li>
247
212
  </ul>
248
213
  </div>
@@ -265,116 +230,81 @@ const Pagination: FunctionComponent<ComponentProps> = (
265
230
 
266
231
  <div className="md:hidden">
267
232
  <div className="inline-flex -space-x-px rounded-md shadow-sm">
268
- <ul role="list">
269
- <li
270
- role="button"
271
- tabIndex={isPreviousDisabled ? -1 : 0}
272
- aria-disabled={isPreviousDisabled}
273
- aria-label="Go to previous page"
274
- onClick={() => {
275
- let currentPageNumber: number = props.currentPageNumber;
276
-
277
- if (typeof currentPageNumber === "string") {
278
- currentPageNumber = parseInt(currentPageNumber);
279
- }
280
-
281
- if (props.onNavigateToPage && !isPreviousDisabled) {
282
- props.onNavigateToPage(
283
- currentPageNumber - 1,
284
- props.itemsOnPage,
285
- );
286
- }
287
- }}
288
- onKeyDown={(e: React.KeyboardEvent) => {
289
- if (
290
- (e.key === "Enter" || e.key === " ") &&
291
- !isPreviousDisabled
292
- ) {
293
- e.preventDefault();
233
+ <ul className="flex" role="list">
234
+ <li className="flex">
235
+ <button
236
+ type="button"
237
+ disabled={isPreviousDisabled}
238
+ aria-label="Go to previous page"
239
+ onClick={() => {
294
240
  let currentPageNumber: number = props.currentPageNumber;
241
+
295
242
  if (typeof currentPageNumber === "string") {
296
243
  currentPageNumber = parseInt(currentPageNumber);
297
244
  }
298
- if (props.onNavigateToPage) {
245
+
246
+ if (props.onNavigateToPage && !isPreviousDisabled) {
299
247
  props.onNavigateToPage(
300
248
  currentPageNumber - 1,
301
249
  props.itemsOnPage,
302
250
  );
303
251
  }
304
- }
305
- }}
306
- className={` inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 ${
307
- isPreviousDisabled
308
- ? "bg-gray-100"
309
- : "hover:bg-gray-50 cursor-pointer"
310
- }`}
311
- >
312
- <span className="page-link">Previous</span>
252
+ }}
253
+ className={` inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500 ${
254
+ isPreviousDisabled
255
+ ? "bg-gray-100 cursor-not-allowed"
256
+ : "hover:bg-gray-50 cursor-pointer"
257
+ }`}
258
+ >
259
+ <span className="page-link">Previous</span>
260
+ </button>
313
261
  </li>
314
- <li
315
- role="button"
316
- tabIndex={isCurrentPageButtonDisabled ? -1 : 0}
317
- aria-current="page"
318
- aria-label={`Page ${props.currentPageNumber}, click to change page`}
319
- data-testid="current-page-link-mobile"
320
- className={` z-10 inline-flex items-center border border-x-0 border-gray-300 hover:bg-gray-50 px-4 py-2 text-sm font-medium text-text-600 cursor-pointer ${
321
- isCurrentPageButtonDisabled ? "bg-gray-100" : ""
322
- }`}
323
- onClick={() => {
324
- if (!isHasMoreMode) {
325
- setShowPaginationModel(true);
326
- }
327
- }}
328
- onKeyDown={(e: React.KeyboardEvent) => {
329
- if ((e.key === "Enter" || e.key === " ") && !isHasMoreMode) {
330
- e.preventDefault();
331
- setShowPaginationModel(true);
332
- }
333
- }}
334
- >
335
- <span>{props.currentPageNumber}</span>
262
+ <li className="flex">
263
+ <button
264
+ type="button"
265
+ disabled={isCurrentPageButtonDisabled}
266
+ aria-current="page"
267
+ aria-label={`Page ${props.currentPageNumber}, current page. Select to jump to another page.`}
268
+ data-testid="current-page-link-mobile"
269
+ className={` z-10 inline-flex items-center border border-x-0 border-gray-300 hover:bg-gray-50 px-4 py-2 text-sm font-medium text-text-600 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500 ${
270
+ isCurrentPageButtonDisabled ? "bg-gray-100" : ""
271
+ }`}
272
+ onClick={() => {
273
+ if (!isHasMoreMode) {
274
+ setShowPaginationModel(true);
275
+ }
276
+ }}
277
+ >
278
+ <span>{props.currentPageNumber}</span>
279
+ </button>
336
280
  </li>
337
- <li
338
- role="button"
339
- tabIndex={isNextDisabled ? -1 : 0}
340
- aria-disabled={isNextDisabled}
341
- aria-label="Go to next page"
342
- onClick={() => {
343
- let currentPageNumber: number = props.currentPageNumber;
344
-
345
- if (typeof currentPageNumber === "string") {
346
- currentPageNumber = parseInt(currentPageNumber);
347
- }
348
-
349
- if (props.onNavigateToPage && !isNextDisabled) {
350
- props.onNavigateToPage(
351
- currentPageNumber + 1,
352
- props.itemsOnPage,
353
- );
354
- }
355
- }}
356
- onKeyDown={(e: React.KeyboardEvent) => {
357
- if ((e.key === "Enter" || e.key === " ") && !isNextDisabled) {
358
- e.preventDefault();
281
+ <li className="flex">
282
+ <button
283
+ type="button"
284
+ disabled={isNextDisabled}
285
+ aria-label="Go to next page"
286
+ onClick={() => {
359
287
  let currentPageNumber: number = props.currentPageNumber;
288
+
360
289
  if (typeof currentPageNumber === "string") {
361
290
  currentPageNumber = parseInt(currentPageNumber);
362
291
  }
363
- if (props.onNavigateToPage) {
292
+
293
+ if (props.onNavigateToPage && !isNextDisabled) {
364
294
  props.onNavigateToPage(
365
295
  currentPageNumber + 1,
366
296
  props.itemsOnPage,
367
297
  );
368
298
  }
369
- }
370
- }}
371
- className={` inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 ${
372
- isNextDisabled
373
- ? "bg-gray-100"
374
- : " hover:bg-gray-50 cursor-pointer"
375
- }`}
376
- >
377
- <span>Next</span>
299
+ }}
300
+ className={` inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500 ${
301
+ isNextDisabled
302
+ ? "bg-gray-100 cursor-not-allowed"
303
+ : " hover:bg-gray-50 cursor-pointer"
304
+ }`}
305
+ >
306
+ <span>Next</span>
307
+ </button>
378
308
  </li>
379
309
  </ul>
380
310
  </div>
@@ -70,5 +70,22 @@ if (ShouldClickhouseSslEnable &&
70
70
  }
71
71
  export const dataSourceOptions = options;
72
72
  export const ingestDataSourceOptions = Object.assign(Object.assign({}, options), { max_open_connections: MaxClickhouseIngestConnections });
73
+ /*
74
+ * Dedicated pool for schema sync + data migrations. The 58s request_timeout
75
+ * above is a socket *idle* timer (see the note on request_timeout) sized for
76
+ * dashboard reads sitting behind nginx's 60s proxy_read_timeout. Migrations
77
+ * do NOT go through nginx (the app connects straight to clickhouse:8123), and
78
+ * a single migration statement — an ON CLUSTER DDL, an MV / projection
79
+ * rebuild, or a type/codec-rewrite MODIFY COLUMN on a multi-billion-row
80
+ * telemetry table — can legitimately stream zero bytes for many minutes,
81
+ * which the 58s idle timer would destroy mid-flight ("Timeout error.") and
82
+ * crash the boot process. Give migrations a much higher idle ceiling. It is
83
+ * finite (not 0) on purpose: a genuinely dead connection / network black hole
84
+ * must still fail eventually rather than hang forever. Long statements should
85
+ * additionally carry send_progress_in_http_headers (see MigrationExecuteOptions
86
+ * in AnalyticsDatabaseService) so the socket stays non-idle, and a server-side
87
+ * SETTINGS max_execution_time so ClickHouse remains the authoritative cap.
88
+ */
89
+ export const migrationDataSourceOptions = Object.assign(Object.assign({}, options), { request_timeout: 30 * 60 * 1000 });
73
90
  export const testDataSourceOptions = dataSourceOptions;
74
91
  //# sourceMappingURL=ClickhouseConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClickhouseConfig.js","sourceRoot":"","sources":["../../../../Server/Infrastructure/ClickhouseConfig.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAIhD,MAAM,YAAY,GAAW,qBAAqB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAEtE,MAAM,cAAc,GAAa,cAAc,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;AAC9E,MAAM,cAAc,GAAW,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;AAEnE,MAAM,OAAO,GAAkC;IAC7C,GAAG,EAAE,GAAG,YAAY,MAAM,cAAc,CAAC,QAAQ,EAAE,IAAI,cAAc,EAAE;IACvE,QAAQ,EAAE,kBAAkB;IAC5B,QAAQ,EAAE,kBAAkB;IAC5B,QAAQ,EAAE,kBAAkB;IAC5B,WAAW,EAAE,WAAW;IACxB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,EAAE,KAAM;IACvB;;;;;OAKG;IACH,oBAAoB,EAAE,wBAAwB;IAC9C;;;;;;;;;;OAUG;IACH,WAAW,EAAE;QACX,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,IAAI;KACf;CACF,CAAC;AAEF,IAAI,yBAAyB,IAAI,eAAe,EAAE,CAAC;IACjD,OAAO,CAAC,GAAG,GAAG;QACZ,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,IACE,yBAAyB;IACzB,eAAe;IACf,iBAAiB;IACjB,gBAAgB,EAChB,CAAC;IACD,OAAO,CAAC,GAAG,GAAG;QACZ,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;QACrC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC;QACpC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAkC,OAAO,CAAC;AAExE,MAAM,CAAC,MAAM,uBAAuB,mCAC/B,OAAO,KACV,oBAAoB,EAAE,8BAA8B,GACrD,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAChC,iBAAiB,CAAC"}
1
+ {"version":3,"file":"ClickhouseConfig.js","sourceRoot":"","sources":["../../../../Server/Infrastructure/ClickhouseConfig.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAIhD,MAAM,YAAY,GAAW,qBAAqB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAEtE,MAAM,cAAc,GAAa,cAAc,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;AAC9E,MAAM,cAAc,GAAW,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;AAEnE,MAAM,OAAO,GAAkC;IAC7C,GAAG,EAAE,GAAG,YAAY,MAAM,cAAc,CAAC,QAAQ,EAAE,IAAI,cAAc,EAAE;IACvE,QAAQ,EAAE,kBAAkB;IAC5B,QAAQ,EAAE,kBAAkB;IAC5B,QAAQ,EAAE,kBAAkB;IAC5B,WAAW,EAAE,WAAW;IACxB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,EAAE,KAAM;IACvB;;;;;OAKG;IACH,oBAAoB,EAAE,wBAAwB;IAC9C;;;;;;;;;;OAUG;IACH,WAAW,EAAE;QACX,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,IAAI;KACf;CACF,CAAC;AAEF,IAAI,yBAAyB,IAAI,eAAe,EAAE,CAAC;IACjD,OAAO,CAAC,GAAG,GAAG;QACZ,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,IACE,yBAAyB;IACzB,eAAe;IACf,iBAAiB;IACjB,gBAAgB,EAChB,CAAC;IACD,OAAO,CAAC,GAAG,GAAG;QACZ,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;QACrC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC;QACpC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAkC,OAAO,CAAC;AAExE,MAAM,CAAC,MAAM,uBAAuB,mCAC/B,OAAO,KACV,oBAAoB,EAAE,8BAA8B,GACrD,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,0BAA0B,mCAClC,OAAO,KACV,eAAe,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,GAChC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAChC,iBAAiB,CAAC"}
@@ -8,7 +8,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import logger from "../Utils/Logger";
11
- import { dataSourceOptions, ingestDataSourceOptions, testDataSourceOptions, } from "./ClickhouseConfig";
11
+ import { dataSourceOptions, ingestDataSourceOptions, migrationDataSourceOptions, testDataSourceOptions, } from "./ClickhouseConfig";
12
12
  import { createClient } from "@clickhouse/client";
13
13
  import DatabaseNotConnectedException from "../../Types/Exception/DatabaseNotConnectedException";
14
14
  import Sleep from "../../Types/Sleep";
@@ -150,4 +150,13 @@ export const ClickhouseAppInstance = new ClickhouseDatabase(dataSourceOptions);
150
150
  * sockets when ingest is bursting.
151
151
  */
152
152
  export const ClickhouseIngestInstance = new ClickhouseDatabase(ingestDataSourceOptions);
153
+ /*
154
+ * Separate pool for schema sync + data migrations. Identical to the App pool
155
+ * except for a much higher request_timeout (see migrationDataSourceOptions):
156
+ * the App pool's 58s socket-idle timer is correct for dashboard reads but
157
+ * would destroy a long-running migration DDL/mutation mid-flight and crash
158
+ * boot. Schema sync and migrations route through this instance via
159
+ * MigrationExecuteOptions (AnalyticsDatabaseService).
160
+ */
161
+ export const ClickhouseMigrationInstance = new ClickhouseDatabase(migrationDataSourceOptions);
153
162
  //# sourceMappingURL=ClickhouseDatabase.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClickhouseDatabase.js","sourceRoot":"","sources":["../../../../Server/Infrastructure/ClickhouseDatabase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClickhouseDatabase.js","sourceRoot":"","sources":["../../../../Server/Infrastructure/ClickhouseDatabase.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { WorkflowHostname } from "../EnvironmentConfig";
11
- import { ClickhouseAppInstance, ClickhouseIngestInstance, } from "../Infrastructure/ClickhouseDatabase";
11
+ import { ClickhouseAppInstance, ClickhouseIngestInstance, ClickhouseMigrationInstance, } from "../Infrastructure/ClickhouseDatabase";
12
12
  import ClusterKeyAuthorization from "../Middleware/ClusterKeyAuthorization";
13
13
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
14
14
  import ModelPermission from "../Types/AnalyticsDatabase/ModelPermission";
@@ -40,6 +40,29 @@ import Typeof from "../../Types/Typeof";
40
40
  import API from "../../Utils/API";
41
41
  import AggregationType from "../../Types/BaseDatabase/AggregationType";
42
42
  import ModelEventType from "../../Types/Realtime/ModelEventType";
43
+ /**
44
+ * Standard options for every schema-sync / data-migration statement. Two
45
+ * layers of protection against the socket-idle `request_timeout` killing a
46
+ * long migration:
47
+ * 1. `useMigrationConnection` routes through ClickhouseMigrationInstance
48
+ * (30-minute idle ceiling) — reliable even for pure-DDL / ON CLUSTER
49
+ * coordination that streams no bytes at all.
50
+ * 2. `send_progress_in_http_headers` makes the server emit periodic
51
+ * X-ClickHouse-Progress header lines for data-rewriting statements
52
+ * (MODIFY COLUMN rewrites, MATERIALIZE, INSERT...SELECT), keeping the
53
+ * socket non-idle so the request completes instead of timing out.
54
+ * Pass this as the second arg to `execute` / `executeQuery` from migration
55
+ * code. The schema-mutating helpers on this service default to it already.
56
+ */
57
+ export const MigrationExecuteOptions = {
58
+ useMigrationConnection: true,
59
+ clickhouseSettings: {
60
+ send_progress_in_http_headers: 1,
61
+ // Emit a progress header every 10s — well under the App pool's 58s and the
62
+ // migration pool's 30-minute idle ceiling.
63
+ http_headers_progress_interval_ms: "10000",
64
+ },
65
+ };
43
66
  const insertDedupContext = new AsyncLocalStorage();
44
67
  export function runWithInsertDedup(tokenBase, fn) {
45
68
  return insertDedupContext.run({ tokenBase, chunkIndexByTable: new Map() }, fn);
@@ -61,8 +84,15 @@ export default class AnalyticsDatabaseService extends BaseService {
61
84
  else {
62
85
  this.ingestDatabase = ClickhouseIngestInstance;
63
86
  }
87
+ /*
88
+ * Migrations route through their own pool (higher socket-idle timeout) via
89
+ * MigrationExecuteOptions. In tests `data.database` is the in-test instance,
90
+ * so reuse it there to keep tests on a single mocked client.
91
+ */
92
+ this.migrationDatabase = data.database || ClickhouseMigrationInstance;
64
93
  this.databaseClient = this.database.getDataSource();
65
94
  this.ingestDatabaseClient = this.ingestDatabase.getDataSource();
95
+ this.migrationDatabaseClient = this.migrationDatabase.getDataSource();
66
96
  this.statementGenerator = new StatementGenerator({
67
97
  modelType: this.modelType,
68
98
  database: this.database,
@@ -228,11 +258,14 @@ export default class AnalyticsDatabaseService extends BaseService {
228
258
  }
229
259
  async addColumnInDatabase(column) {
230
260
  const statement = this.statementGenerator.toAddColumnStatement(column);
231
- await this.execute(statement);
261
+ // Schema-sync / migration-only path: route through the migration pool so a
262
+ // column add that backfills a DEFAULT/MATERIALIZED expression on a large
263
+ // table is not destroyed at the App pool's 58s socket-idle timeout.
264
+ await this.execute(statement, MigrationExecuteOptions);
232
265
  // Add skip index separately (ClickHouse requires ADD INDEX as a separate ALTER statement)
233
266
  const indexStatement = this.statementGenerator.toAddSkipIndexStatement(column);
234
267
  if (indexStatement) {
235
- await this.execute(indexStatement);
268
+ await this.execute(indexStatement, MigrationExecuteOptions);
236
269
  }
237
270
  }
238
271
  async dropColumnInDatabase(columnName) {
@@ -244,9 +277,9 @@ export default class AnalyticsDatabaseService extends BaseService {
244
277
  return col.key === columnName;
245
278
  });
246
279
  if (column === null || column === void 0 ? void 0 : column.skipIndex) {
247
- await this.execute(this.statementGenerator.toDropSkipIndexStatement(column.skipIndex.name));
280
+ await this.execute(this.statementGenerator.toDropSkipIndexStatement(column.skipIndex.name), MigrationExecuteOptions);
248
281
  }
249
- await this.execute(this.statementGenerator.toDropColumnStatement(columnName));
282
+ await this.execute(this.statementGenerator.toDropColumnStatement(columnName), MigrationExecuteOptions);
250
283
  }
251
284
  async doesColumnExist(columnName) {
252
285
  // Columns live on the physical (local) storage table in cluster mode.
@@ -290,7 +323,7 @@ export default class AnalyticsDatabaseService extends BaseService {
290
323
  logger.info(`${tableName}.${data.columnName} already has ${data.expectedCodecValue}, skipping`, { tableName });
291
324
  return;
292
325
  }
293
- await this.execute(`ALTER TABLE ${tableName} MODIFY COLUMN ${data.columnName} ${data.columnType} CODEC(${data.codec}) SETTINGS mutations_sync=0`);
326
+ await this.execute(`ALTER TABLE ${tableName} MODIFY COLUMN ${data.columnName} ${data.columnType} CODEC(${data.codec}) SETTINGS mutations_sync=0`, MigrationExecuteOptions);
294
327
  logger.info(`Applied ${data.codec} codec to ${tableName}.${data.columnName} (async)`, { tableName });
295
328
  }
296
329
  async findBy(findBy) {
@@ -892,9 +925,13 @@ export default class AnalyticsDatabaseService extends BaseService {
892
925
  this.databaseClient = this.database.getDataSource();
893
926
  this.ingestDatabase = ClickhouseIngestInstance;
894
927
  this.ingestDatabaseClient = this.ingestDatabase.getDataSource();
928
+ this.migrationDatabase = ClickhouseMigrationInstance;
929
+ this.migrationDatabaseClient = this.migrationDatabase.getDataSource();
895
930
  }
896
931
  async execute(statement, options) {
897
- const client = this.getDatabaseClient();
932
+ const client = (options === null || options === void 0 ? void 0 : options.useMigrationConnection)
933
+ ? this.getMigrationClient()
934
+ : this.getDatabaseClient();
898
935
  const query = statement instanceof Statement ? statement.query : statement;
899
936
  const queryParams = statement instanceof Statement ? statement.query_params : undefined;
900
937
  return (await client.exec(Object.assign(Object.assign({ query: query, query_params: queryParams || undefined }, ((options === null || options === void 0 ? void 0 : options.clickhouseSettings)
@@ -902,7 +939,9 @@ export default class AnalyticsDatabaseService extends BaseService {
902
939
  : {})), ((options === null || options === void 0 ? void 0 : options.queryId) ? { query_id: options.queryId } : {}))));
903
940
  }
904
941
  async executeQuery(statement, options) {
905
- const client = this.getDatabaseClient();
942
+ const client = (options === null || options === void 0 ? void 0 : options.useMigrationConnection)
943
+ ? this.getMigrationClient()
944
+ : this.getDatabaseClient();
906
945
  const query = statement instanceof Statement ? statement.query : statement;
907
946
  const queryParams = statement instanceof Statement ? statement.query_params : undefined;
908
947
  return await client.query(Object.assign(Object.assign({ query: query, format: "JSON", query_params: queryParams || undefined }, ((options === null || options === void 0 ? void 0 : options.clickhouseSettings)
@@ -937,6 +976,18 @@ export default class AnalyticsDatabaseService extends BaseService {
937
976
  }
938
977
  return this.ingestDatabaseClient;
939
978
  }
979
+ getMigrationClient() {
980
+ if (!this.migrationDatabase) {
981
+ this.useDefaultDatabase();
982
+ }
983
+ if (!this.migrationDatabaseClient && this.migrationDatabase) {
984
+ this.migrationDatabaseClient = this.migrationDatabase.getDataSource();
985
+ }
986
+ if (!this.migrationDatabaseClient) {
987
+ throw new Exception(ExceptionCode.DatabaseNotConnectedException, "ClickHouse migration client is not connected");
988
+ }
989
+ return this.migrationDatabaseClient;
990
+ }
940
991
  async onUpdateSuccess(onUpdate, _updatedItemIds) {
941
992
  // A place holder method used for overriding.
942
993
  return Promise.resolve(onUpdate);