Using ElectricSQL for the run page data

This commit is contained in:
Matt Aitken
2024-08-29 17:23:41 +01:00
parent 723753b9ea
commit cbb95f244f
6 changed files with 109 additions and 8 deletions
+1
View File
@@ -31,6 +31,7 @@ const EnvironmentSchema = z.object({
REMIX_APP_PORT: z.string().optional(),
LOGIN_ORIGIN: z.string().default("http://localhost:3030"),
APP_ORIGIN: z.string().default("http://localhost:3030"),
ELECTRIC_ORIGIN: z.string().default("http://localhost:3060"),
APP_ENV: z.string().default(process.env.NODE_ENV),
SERVICE_NAME: z.string().default("trigger.dev webapp"),
SECRET_STORE: SecretStoreOptionsSchema.default("DATABASE"),
+26
View File
@@ -0,0 +1,26 @@
import { useShape } from "@electric-sql/react";
import { createTraceTreeFromEvents, prepareTrace } from "~/utils/taskEvent";
import { QueriedEvent } from "~/v3/eventRepository.server";
type TraceInput = {
origin: string;
traceId: string;
spanId: string;
};
export type Trace = ReturnType<typeof createTraceTreeFromEvents>;
export type TraceEvent = NonNullable<Trace["events"][number]>;
export function useTrace({ origin, traceId, spanId }: TraceInput) {
const { isUpToDate, data } = useShape({
url: `${origin}/sync/traces/${traceId}`,
});
const events = prepareTrace(data as QueriedEvent[]);
if (!events) {
return { isUpToDate, trace: undefined };
}
const trace = createTraceTreeFromEvents(events, spanId);
return { isUpToDate, trace };
}
@@ -1,3 +1,4 @@
import { useShape } from "@electric-sql/react";
import {
ArrowUturnLeftIcon,
BoltSlashIcon,
@@ -80,8 +81,9 @@ import {
} from "~/utils/pathBuilder";
import { SpanView } from "../resources.orgs.$organizationSlug.projects.v3.$projectParam.runs.$runParam.spans.$spanParam/route";
import { useCurrentPlan } from "../_app.orgs.$organizationSlug/route";
type TraceEvent = NonNullable<SerializeFrom<typeof loader>["trace"]>["events"][0];
import { Trace, TraceEvent, useTrace } from "~/hooks/useTrace";
import { trace } from "console";
import { useAppOrigin } from "~/hooks/useAppOrigin";
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
const userId = await requireUserId(request);
@@ -100,9 +102,8 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
return json({
run: result.run,
trace: result.trace,
maximumLiveReloadingSetting: env.MAXIMUM_LIVE_RELOADING_EVENTS,
resizeSettings,
maximumLiveReloadingSetting: env.MAXIMUM_LIVE_RELOADING_EVENTS,
});
};
@@ -114,8 +115,15 @@ function getSpanId(location: Location<any>): string | undefined {
}
export default function Page() {
const { run, trace, resizeSettings, maximumLiveReloadingSetting } =
useLoaderData<typeof loader>();
const { run, resizeSettings, maximumLiveReloadingSetting } = useLoaderData<typeof loader>();
const appOrigin = useAppOrigin();
const { location, replaceSearchParam } = useReplaceLocation();
const { isUpToDate, trace } = useTrace({
origin: appOrigin,
traceId: run.traceId,
spanId: getSpanId(location) ?? run.spanId,
});
const user = useUser();
const organization = useOrganization();
const project = useProject();
@@ -223,7 +231,11 @@ export default function Page() {
);
}
function TraceView({ run, trace, maximumLiveReloadingSetting, resizeSettings }: LoaderData) {
type TraceData = Pick<LoaderData, "run" | "maximumLiveReloadingSetting" | "resizeSettings"> & {
trace: Trace | undefined;
};
function TraceView({ run, trace, maximumLiveReloadingSetting, resizeSettings }: TraceData) {
const organization = useOrganization();
const project = useProject();
const { location, replaceSearchParam } = useReplaceLocation();
@@ -301,7 +313,7 @@ function TraceView({ run, trace, maximumLiveReloadingSetting, resizeSettings }:
);
}
function NoLogsView({ run, resizeSettings }: LoaderData) {
function NoLogsView({ run, resizeSettings }: TraceData) {
const plan = useCurrentPlan();
const organization = useOrganization();
@@ -0,0 +1,31 @@
import type { LoaderFunctionArgs } from "@remix-run/node";
import { env } from "~/env.server";
export async function loader({ params, request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const { table } = params;
const originUrl = new URL(`${env.ELECTRIC_ORIGIN}/v1/shape/public."TaskEvent"`);
url.searchParams.forEach((value, key) => {
originUrl.searchParams.set(key, value);
});
originUrl.searchParams.set("where", `"traceId"='${params.traceId}'`);
// When proxying long-polling requests, content-encoding & content-length are added
// erroneously (saying the body is gzipped when it's not) so we'll just remove
// them to avoid content decoding errors in the browser.
//
// Similar-ish problem to https://github.com/wintercg/fetch/issues/23
let response = await fetch(originUrl.toString());
if (response.headers.get(`content-encoding`)) {
const headers = new Headers(response.headers);
headers.delete(`content-encoding`);
headers.delete(`content-length`);
response = new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers,
});
}
return response;
}
+1
View File
@@ -46,6 +46,7 @@
"@conform-to/react": "^0.6.1",
"@conform-to/zod": "^0.6.1",
"@depot/sdk-node": "^0.5.0",
"@electric-sql/react": "^0.3.1",
"@headlessui/react": "^1.7.8",
"@heroicons/react": "^2.0.12",
"@internationalized/date": "^3.5.1",
+30
View File
@@ -231,6 +231,9 @@ importers:
'@depot/sdk-node':
specifier: ^0.5.0
version: 0.5.0
'@electric-sql/react':
specifier: ^0.3.1
version: 0.3.1(react@18.2.0)
'@headlessui/react':
specifier: ^1.7.8
version: 1.7.8(react-dom@18.2.0)(react@18.2.0)
@@ -4124,6 +4127,25 @@ packages:
'@connectrpc/connect-node': 0.13.2(@bufbuild/protobuf@1.7.2)
dev: false
/@electric-sql/client@0.3.2:
resolution: {integrity: sha512-DVOtrIfg7xlXpU95F53MnLXLeIn1eYkSRz01vj63NzZZ7bf6vLSHzNKvil0413C3U3769btfQytGNWmsb744WQ==}
optionalDependencies:
'@rollup/rollup-darwin-arm64': 4.21.1
dev: false
/@electric-sql/react@0.3.1(react@18.2.0):
resolution: {integrity: sha512-U+7ssfS+4UuGYXTyqGqXJGN04hrwjI8qKcv5l1br59EX93yfrFVVEfRsCQIe0mTiFTS/im9k+SUBIPrC/g8n2A==}
peerDependencies:
react: ^18.3.1
peerDependenciesMeta:
react:
optional: true
dependencies:
'@electric-sql/client': 0.3.2
react: 18.2.0
use-sync-external-store: 1.2.2(react@18.2.0)
dev: false
/@emotion/hash@0.9.0:
resolution: {integrity: sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==}
dev: true
@@ -11590,6 +11612,14 @@ packages:
dev: true
optional: true
/@rollup/rollup-darwin-arm64@4.21.1:
resolution: {integrity: sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/@rollup/rollup-darwin-x64@4.13.2:
resolution: {integrity: sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A==}
cpu: [x64]