| 426 | } |
| 427 | |
| 428 | async byId(sessionId: string, projectId: string) { |
| 429 | const [sessionRows, hasReplayRows] = await Promise.all([ |
| 430 | clix(this.client) |
| 431 | .select<IClickhouseSession>(['*']) |
| 432 | .from(TABLE_NAMES.sessions, true) |
| 433 | .where('id', '=', sessionId) |
| 434 | .where('project_id', '=', projectId) |
| 435 | .where('sign', '=', 1) |
| 436 | .execute(), |
| 437 | chQuery<{ n: number }>( |
| 438 | `SELECT 1 AS n |
| 439 | FROM ${TABLE_NAMES.session_replay_chunks} |
| 440 | WHERE session_id = ${sqlstring.escape(sessionId)} |
| 441 | AND project_id = ${sqlstring.escape(projectId)} |
| 442 | LIMIT 1` |
| 443 | ), |
| 444 | ]); |
| 445 | |
| 446 | if (!sessionRows[0]) { |
| 447 | throw new Error('Session not found'); |
| 448 | } |
| 449 | |
| 450 | const session = transformSession(sessionRows[0]); |
| 451 | |
| 452 | return { |
| 453 | ...session, |
| 454 | hasReplay: hasReplayRows.length > 0, |
| 455 | }; |
| 456 | } |
| 457 | } |
| 458 | |
| 459 | export const sessionService = new SessionService(ch); |