From a7e8515c4290ef07d5cd5946af5c5a67728ecb9c Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Thu, 7 Mar 2024 15:23:24 +0100 Subject: [PATCH] Fix QUERY_WITH_SAME_ID_IS_ALREADY_RUNNING by appending query_id (#4173) --- .../operations/providers/clickhouse-client.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/packages/services/api/src/modules/operations/providers/clickhouse-client.ts b/packages/services/api/src/modules/operations/providers/clickhouse-client.ts index 6bdb4af03..d9fd6547b 100644 --- a/packages/services/api/src/modules/operations/providers/clickhouse-client.ts +++ b/packages/services/api/src/modules/operations/providers/clickhouse-client.ts @@ -85,6 +85,8 @@ export class ClickHouse { printWithValues(query).replace(/\n/g, ' ').replace(/\s+/g, ' '), ); + let retries = 0; + const response = await this.httpClient .post>(endpoint, { context: { @@ -145,6 +147,39 @@ export class ClickHouse { http: httpAgent, https: httpsAgent, }, + hooks: { + // `beforeRetry` runs first, then `beforeRequest` + beforeRequest: [ + options => { + if ( + retries > 0 && + options.searchParams && + typeof options.searchParams === 'object' && + 'query_id' in options.searchParams && + typeof options.searchParams.query_id === 'string' + ) { + // We do it to avoid QUERY_WITH_SAME_ID_IS_ALREADY_RUNNING error in ClickHouse + // Context: https://clickhouse.com/docs/en/interfaces/http + // > Running requests do not stop automatically if the HTTP connection is lost. + // > The optional 'query_id' parameter can be passed as the query ID (any string). + // More context: https://clickhouse.com/docs/en/operations/settings/settings#replace-running-query + // > When using the HTTP interface, the 'query_id' parameter can be passed. + // > If a query from the same user with the same 'query_id' already exists at this time, + // > the behaviour depends on the 'replace_running_query' parameter. + // > Default: throws QUERY_WITH_SAME_ID_IS_ALREADY_RUNNING exception. + options.searchParams.query_id = options.searchParams.query_id.replace( + /-r\d$/, + '-r' + retries, + ); + } + }, + ], + beforeRetry: [ + (_, retryCount) => { + retries = retryCount; + }, + ], + }, }) .then(response => { if (response.exception) {