|
7 | 7 | composeTaskRunVersion, |
8 | 8 | getPayloadField, |
9 | 9 | getTaskRunField, |
10 | | - PAYLOAD_INDEX, |
11 | 10 | TASK_RUN_INDEX, |
12 | 11 | } from "@internal/clickhouse"; |
13 | 12 | import { type RedisOptions } from "@internal/redis"; |
@@ -44,7 +43,8 @@ import { detectBadJsonStrings } from "~/utils/detectBadJsonStrings"; |
44 | 43 | import { calculateErrorFingerprint } from "~/utils/errorFingerprinting"; |
45 | 44 | import { baseWorkerQueue } from "~/runEngine/concerns/workerQueueSplit.server"; |
46 | 45 | import { |
47 | | - insertWithJsonParseRecovery, |
| 46 | + insertWithBadRowSkip, |
| 47 | + insertWithLimitedStrip, |
48 | 48 | type JsonParseRecoveryOutcome, |
49 | 49 | } from "~/v3/eventRepository/sanitizeRowsOnParseError.server"; |
50 | 50 |
|
@@ -114,6 +114,7 @@ export type RunsReplicationServiceOptions = { |
114 | 114 | insertMaxDelayMs?: number; |
115 | 115 | disablePayloadInsert?: boolean; |
116 | 116 | disableErrorFingerprinting?: boolean; |
| 117 | + maxPoisonStripsPerBatch?: number; |
117 | 118 | }; |
118 | 119 |
|
119 | 120 | type PostgresTaskRun = TaskRun & { masterQueue: string }; |
@@ -1133,14 +1134,24 @@ export class RunsReplicationService { |
1133 | 1134 | return insertResult; |
1134 | 1135 | }; |
1135 | 1136 |
|
1136 | | - const outcome = await insertWithJsonParseRecovery({ |
| 1137 | + const outcome = await insertWithLimitedStrip({ |
1137 | 1138 | rows: taskRunInserts, |
1138 | 1139 | contextLabel: "task_runs_v2", |
1139 | 1140 | logger: this.logger, |
1140 | 1141 | logContext: { attempt }, |
1141 | 1142 | insert: (rows) => rawInsert(rows), |
1142 | | - insertSync: (rows) => rawInsert(rows, { async_insert: 0 }), |
| 1143 | + insertSync: (rows) => |
| 1144 | + rawInsert(rows, { async_insert: 0, input_format_parallel_parsing: 0 }), |
| 1145 | + insertAllowingBadRows: (rows) => |
| 1146 | + rawInsert(rows, { |
| 1147 | + async_insert: 0, |
| 1148 | + input_format_parallel_parsing: 0, |
| 1149 | + input_format_allow_errors_num: String(rows.length), |
| 1150 | + input_format_allow_errors_ratio: 1, |
| 1151 | + }), |
1143 | 1152 | stripJsonColumns: stripTaskRunJsonColumns, |
| 1153 | + maxPoisonStrips: this.options.maxPoisonStripsPerBatch, |
| 1154 | + hasMaterializedViews: true, |
1144 | 1155 | }); |
1145 | 1156 | this.#recordRecoveryOutcome(outcome, "task_runs_v2", taskRunInserts.length); |
1146 | 1157 | return outcome; |
@@ -1176,14 +1187,20 @@ export class RunsReplicationService { |
1176 | 1187 | return insertResult; |
1177 | 1188 | }; |
1178 | 1189 |
|
1179 | | - const outcome = await insertWithJsonParseRecovery({ |
| 1190 | + const outcome = await insertWithBadRowSkip({ |
1180 | 1191 | rows: payloadInserts, |
1181 | 1192 | contextLabel: "raw_task_runs_payload_v1", |
1182 | 1193 | logger: this.logger, |
1183 | 1194 | logContext: { attempt }, |
1184 | 1195 | insert: (rows) => rawInsert(rows), |
1185 | | - insertSync: (rows) => rawInsert(rows, { async_insert: 0 }), |
1186 | | - stripJsonColumns: stripPayloadJsonColumns, |
| 1196 | + insertAllowingBadRows: (rows) => |
| 1197 | + rawInsert(rows, { |
| 1198 | + async_insert: 0, |
| 1199 | + input_format_parallel_parsing: 0, |
| 1200 | + input_format_allow_errors_num: String(rows.length), |
| 1201 | + input_format_allow_errors_ratio: 1, |
| 1202 | + }), |
| 1203 | + hasMaterializedViews: false, |
1187 | 1204 | }); |
1188 | 1205 | this.#recordRecoveryOutcome(outcome, "raw_task_runs_payload_v1", payloadInserts.length); |
1189 | 1206 | return outcome; |
@@ -1587,9 +1604,3 @@ function stripTaskRunJsonColumns(row: TaskRunInsertArray): TaskRunInsertArray { |
1587 | 1604 | stripped[TASK_RUN_INDEX.error] = STRIPPED_JSON; |
1588 | 1605 | return stripped; |
1589 | 1606 | } |
1590 | | - |
1591 | | -function stripPayloadJsonColumns(row: PayloadInsertArray): PayloadInsertArray { |
1592 | | - const stripped = [...row] as PayloadInsertArray; |
1593 | | - stripped[PAYLOAD_INDEX.payload] = STRIPPED_JSON; |
1594 | | - return stripped; |
1595 | | -} |
|
0 commit comments