Skip to content

Commit 01f7c39

Browse files
committed
fix(webapp): restore Postgres fallback for non-ClickHouse OTLP spans
Environments with taskEventStore = 'taskEvent' / 'taskEventPartitioned' (Postgres-backed runs not yet migrated to ClickHouse) were hitting a throw in buildEventRepository when the org-scoped ClickHouse factory received those store values. The throw happened inside the grouping loop of #exportEvents, causing the entire OTLP request to return HTTP 500 — which the OpenTelemetry collector treats as non-retryable, silently dropping the full batch. Fix: guard the getEventRepositoryForOrganizationSync call in #exportEvents to only invoke the ClickHouse factory for clickhouse/clickhouse_v2 stores. All other store values (taskEvent, taskEventPartitioned, postgres) route directly to the existing Postgres eventRepository, mirroring the pattern already used by resolveEventRepositoryForStore and getEventRepositoryForStore in eventRepository/index.server.ts. Also wrap the factory call in a try/catch that falls back to Postgres so any future unexpected store values in an OTLP batch degrade gracefully instead of failing the whole request.
1 parent 9cb6fd1 commit 01f7c39

1 file changed

Lines changed: 20 additions & 4 deletions

File tree

apps/webapp/app/v3/otlpExporter.server.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type { ClickhouseFactory } from "~/services/clickhouse/clickhouseFactory.
2424
import { clickhouseFactory } from "~/services/clickhouse/clickhouseFactoryInstance.server";
2525

2626
import { generateSpanId } from "./eventRepository/common.server";
27+
import { eventRepository } from "./eventRepository/eventRepository.server";
2728
import type {
2829
CreatableEventKind,
2930
CreatableEventStatus,
@@ -120,10 +121,25 @@ class OTLPExporter {
120121
const routeKey = `${event.organizationId}\0${taskEventStore}`;
121122
let resolved = routeCache.get(routeKey);
122123
if (!resolved) {
123-
resolved = this._clickhouseFactory.getEventRepositoryForOrganizationSync(
124-
taskEventStore,
125-
event.organizationId
126-
);
124+
// Non-ClickHouse stores (taskEvent / taskEventPartitioned) are Postgres-backed.
125+
// The ClickHouse factory only handles clickhouse/clickhouse_v2 and throws otherwise.
126+
if (taskEventStore !== "clickhouse" && taskEventStore !== "clickhouse_v2") {
127+
resolved = { key: "postgres:default", repository: eventRepository };
128+
} else {
129+
try {
130+
resolved = this._clickhouseFactory.getEventRepositoryForOrganizationSync(
131+
taskEventStore,
132+
event.organizationId
133+
);
134+
} catch (error) {
135+
logger.error("[OTLPExporter] Failed to resolve ClickHouse event repository", {
136+
taskEventStore,
137+
organizationId: event.organizationId,
138+
error: error instanceof Error ? error.message : error,
139+
});
140+
resolved = { key: "postgres:default", repository: eventRepository };
141+
}
142+
}
127143
routeCache.set(routeKey, resolved);
128144
}
129145

0 commit comments

Comments
 (0)