Skip to content

Commit e3c47af

Browse files
authored
log-server: fix serveur crash when run exists (#160)
1 parent 6753790 commit e3c47af

File tree

3 files changed

+45
-17
lines changed

3 files changed

+45
-17
lines changed

.changeset/poor-cameras-battle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@lightmill/log-server': patch
3+
---
4+
5+
fix crashes when trying to create a run that already exists

packages/log-server/src/app.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
/* eslint-disable @typescript-eslint/no-namespace */
22
import express from 'express';
33
import { zodiosContext } from '@zodios/express';
4-
import { LogFilter, Store } from './store.js';
4+
import { LogFilter, Store, StoreError } from './store.js';
55
import session from 'cookie-session';
6-
import { SqliteError } from 'better-sqlite3';
76
import { NextFunction, Request, RequestHandler, Response } from 'express';
87
import { api } from './api.js';
98
import { csvExportStream, jsonExportStream } from './export.js';
@@ -149,11 +148,10 @@ export function createLogServer({
149148
},
150149
});
151150
} catch (e) {
152-
if (e instanceof SqliteError && e.code === 'SQLITE_CONSTRAINT') {
151+
if (e instanceof StoreError && e.code === 'RUN_EXISTS') {
153152
res.status(400).json({
154153
status: 'error',
155-
message:
156-
'Could not add run, probably because a run with that ID already exists for this experiment',
154+
message: e.message,
157155
});
158156
return;
159157
}

packages/log-server/src/store.ts

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from 'node:fs/promises';
22
import path from 'node:path';
33
import * as url from 'node:url';
4-
import SQliteDB from 'better-sqlite3';
4+
import SQliteDB, { SqliteError } from 'better-sqlite3';
55
import {
66
Kysely,
77
FileMigrationProvider,
@@ -78,17 +78,30 @@ export class Store {
7878
experimentId: string;
7979
createdAt: Date;
8080
}) {
81-
let result = await this.#db
82-
.insertInto('run')
83-
.values({
84-
runId,
85-
experimentId,
86-
createdAt: createdAt.toISOString(),
87-
status: 'running',
88-
})
89-
.returning(['runId', 'experimentId'])
90-
.executeTakeFirstOrThrow();
91-
return { runId: result.runId, experimentId: result.experimentId };
81+
try {
82+
let result = await this.#db
83+
.insertInto('run')
84+
.values({
85+
runId,
86+
experimentId,
87+
createdAt: createdAt.toISOString(),
88+
status: 'running',
89+
})
90+
.returning(['runId', 'experimentId'])
91+
.executeTakeFirstOrThrow();
92+
return { runId: result.runId, experimentId: result.experimentId };
93+
} catch (e) {
94+
if (
95+
e instanceof SqliteError &&
96+
e.code === 'SQLITE_CONSTRAINT_PRIMARYKEY'
97+
) {
98+
throw new StoreError(
99+
`run "${runId}" already exists for experiment "${experimentId}".`,
100+
'RUN_EXISTS'
101+
);
102+
}
103+
throw e;
104+
}
92105
}
93106

94107
async getRun(experimentId: string, runId: string) {
@@ -295,3 +308,15 @@ export type Log = {
295308
clientDate?: Date;
296309
values: JsonObject;
297310
};
311+
312+
type StoreErrorCode = 'RUN_EXISTS';
313+
export class StoreError extends Error {
314+
code: StoreErrorCode;
315+
cause?: Error;
316+
constructor(message: string, code: StoreErrorCode, cause?: Error) {
317+
super(message);
318+
this.name = 'StoreError';
319+
this.code = code;
320+
this.cause = cause;
321+
}
322+
}

0 commit comments

Comments
 (0)