Skip to content

Commit 6586bc6

Browse files
committed
fix: move distinct operations/providers queries to PromptPresenter, parallelize in dashboard loader
1 parent f78675f commit 6586bc6

File tree

4 files changed

+78
-53
lines changed

4 files changed

+78
-53
lines changed

CLAUDE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ pnpm run dev --filter webapp # Run webapp (http://localhost:3030)
1818
pnpm run dev --filter trigger.dev --filter "@trigger.dev/*" # Watch CLI and packages
1919
```
2020

21+
### Verifying Webapp Changes
22+
23+
**Never run `pnpm run build --filter webapp` to verify changes.** Building proves almost nothing about correctness. Instead, run typecheck from the repo root:
24+
25+
```bash
26+
pnpm run typecheck --filter webapp # ~1-2 minutes
27+
```
28+
29+
Only run typecheck after major changes (new files, significant refactors, schema changes). For small edits, trust the types and let CI catch issues.
30+
2131
## Testing
2232

2333
We use vitest exclusively. **Never mock anything** - use testcontainers instead.

apps/webapp/CLAUDE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
Remix 2.1.0 app serving as the main API, dashboard, and orchestration engine. Uses an Express server (`server.ts`).
44

5+
## Verifying Changes
6+
7+
**Never run `pnpm run build --filter webapp` to verify changes.** Building proves almost nothing about correctness. Instead, run typecheck from the repo root:
8+
9+
```bash
10+
pnpm run typecheck --filter webapp # ~1-2 minutes
11+
```
12+
13+
Only run typecheck after major changes (new files, significant refactors, schema changes). For small edits, trust the types and let CI catch issues.
14+
515
## Key File Locations
616

717
- **Trigger API**: `app/routes/api.v1.tasks.$taskId.trigger.ts`

apps/webapp/app/presenters/v3/PromptPresenter.server.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,52 @@ export class PromptPresenter extends BasePresenter {
365365
}
366366
return rows.map((r) => r.prompt_slug);
367367
}
368+
369+
async getDistinctOperations(
370+
organizationId: string,
371+
projectId: string,
372+
environmentId: string
373+
): Promise<string[]> {
374+
const queryFn = this.clickhouse.reader.query({
375+
name: "getDistinctOperations",
376+
query: `SELECT DISTINCT operation_id FROM trigger_dev.llm_metrics_v1 WHERE organization_id = {organizationId: String} AND project_id = {projectId: String} AND environment_id = {environmentId: String} AND operation_id != '' ORDER BY operation_id`,
377+
params: z.object({
378+
organizationId: z.string(),
379+
projectId: z.string(),
380+
environmentId: z.string(),
381+
}),
382+
schema: z.object({ operation_id: z.string() }),
383+
});
384+
385+
const [error, rows] = await queryFn({ organizationId, projectId, environmentId });
386+
if (error) {
387+
return [];
388+
}
389+
return rows.map((r) => r.operation_id);
390+
}
391+
392+
async getDistinctProviders(
393+
organizationId: string,
394+
projectId: string,
395+
environmentId: string
396+
): Promise<string[]> {
397+
const queryFn = this.clickhouse.reader.query({
398+
name: "getDistinctProviders",
399+
query: `SELECT DISTINCT gen_ai_system FROM trigger_dev.llm_metrics_v1 WHERE organization_id = {organizationId: String} AND project_id = {projectId: String} AND environment_id = {environmentId: String} AND gen_ai_system != '' ORDER BY gen_ai_system`,
400+
params: z.object({
401+
organizationId: z.string(),
402+
projectId: z.string(),
403+
environmentId: z.string(),
404+
}),
405+
schema: z.object({ gen_ai_system: z.string() }),
406+
});
407+
408+
const [error, rows] = await queryFn({ organizationId, projectId, environmentId });
409+
if (error) {
410+
return [];
411+
}
412+
return rows.map((r) => r.gen_ai_system);
413+
}
368414
}
369415

370416
function encodeCursor(startTime: string, spanId: string): string {

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardKey/route.tsx

Lines changed: 12 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -98,59 +98,18 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
9898
}
9999
}
100100

101-
let possiblePrompts: string[] = [];
102-
if (filters.includes("prompts")) {
103-
const promptPresenter = new PromptPresenter(clickhouseClient);
104-
possiblePrompts = await promptPresenter.getDistinctPromptSlugs(
105-
project.organizationId,
106-
project.id,
107-
environment.id
108-
);
109-
}
110-
111-
let possibleOperations: string[] = [];
112-
if (filters.includes("operations")) {
113-
const queryFn = clickhouseClient.reader.query({
114-
name: "getDistinctOperations",
115-
query: `SELECT DISTINCT operation_id FROM trigger_dev.llm_metrics_v1 WHERE organization_id = {organizationId: String} AND project_id = {projectId: String} AND environment_id = {environmentId: String} AND operation_id != '' ORDER BY operation_id`,
116-
params: z.object({
117-
organizationId: z.string(),
118-
projectId: z.string(),
119-
environmentId: z.string(),
120-
}),
121-
schema: z.object({ operation_id: z.string() }),
122-
});
123-
const [error, rows] = await queryFn({
124-
organizationId: project.organizationId,
125-
projectId: project.id,
126-
environmentId: environment.id,
127-
});
128-
if (!error) {
129-
possibleOperations = rows.map((r) => r.operation_id);
130-
}
131-
}
132-
133-
let possibleProviders: string[] = [];
134-
if (filters.includes("providers")) {
135-
const queryFn = clickhouseClient.reader.query({
136-
name: "getDistinctProviders",
137-
query: `SELECT DISTINCT gen_ai_system FROM trigger_dev.llm_metrics_v1 WHERE organization_id = {organizationId: String} AND project_id = {projectId: String} AND environment_id = {environmentId: String} AND gen_ai_system != '' ORDER BY gen_ai_system`,
138-
params: z.object({
139-
organizationId: z.string(),
140-
projectId: z.string(),
141-
environmentId: z.string(),
142-
}),
143-
schema: z.object({ gen_ai_system: z.string() }),
144-
});
145-
const [error, rows] = await queryFn({
146-
organizationId: project.organizationId,
147-
projectId: project.id,
148-
environmentId: environment.id,
149-
});
150-
if (!error) {
151-
possibleProviders = rows.map((r) => r.gen_ai_system);
152-
}
153-
}
101+
const promptPresenter = new PromptPresenter(clickhouseClient);
102+
const [possiblePrompts, possibleOperations, possibleProviders] = await Promise.all([
103+
filters.includes("prompts")
104+
? promptPresenter.getDistinctPromptSlugs(project.organizationId, project.id, environment.id)
105+
: ([] as string[]),
106+
filters.includes("operations")
107+
? promptPresenter.getDistinctOperations(project.organizationId, project.id, environment.id)
108+
: ([] as string[]),
109+
filters.includes("providers")
110+
? promptPresenter.getDistinctProviders(project.organizationId, project.id, environment.id)
111+
: ([] as string[]),
112+
]);
154113

155114
return typedjson({
156115
...dashboard,

0 commit comments

Comments
 (0)