Skip to content

Commit

Permalink
Updates job run page to show schema initialization errors (#3177)
Browse files Browse the repository at this point in the history
  • Loading branch information
alishakawaguchi authored Jan 22, 2025
1 parent 8be389e commit 7710aa2
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { TanstackQueryProviderIgnore404Errors } from '@/components/providers/query-provider';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@/components/ui/accordion';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { ScrollArea } from '@/components/ui/scroll-area';
import { useQuery } from '@connectrpc/connect-query';
import { Code, Connection, ConnectionService, JobService } from '@neosync/sdk';
import { ReactElement } from 'react';
import { IoAlertCircleOutline } from 'react-icons/io5';

interface JobRunActivityErrorsProps {
jobRunId: string;
jobId: string;
accountId: string;
}

interface InitSchemaReport {
ConnectionId: string;
Errors: { Statement: string; Error: string }[];
}

function parseUint8ArrayToInitSchemaReport(
data: Uint8Array
): InitSchemaReport[] | null {
try {
const jsonString = new TextDecoder().decode(data);
const parsedData: InitSchemaReport[] = JSON.parse(jsonString);
return parsedData;
} catch (error) {
console.error('Error parsing JSON:', error);
return null;
}
}
export default function JobRunActivityErrors(
props: JobRunActivityErrorsProps
): ReactElement {
return (
<TanstackQueryProviderIgnore404Errors>
<JobRunErrorViewer {...props} />
</TanstackQueryProviderIgnore404Errors>
);
}

function JobRunErrorViewer(props: JobRunActivityErrorsProps): ReactElement {
const { jobRunId, accountId } = props;

const { data: runContextData, error: runContextError } = useQuery(
JobService.method.getRunContext,
{
id: { jobRunId, externalId: 'init-schema-report', accountId: accountId },
},
{ enabled: !!jobRunId && !!accountId, retry: false }
);

const { data: connectionsData } = useQuery(
ConnectionService.method.getConnections,
{ accountId },
{ enabled: !!accountId }
);

if (runContextError && runContextError.code === Code.NotFound) {
return <div></div>;
}

const runContext = runContextData?.value
? parseUint8ArrayToInitSchemaReport(runContextData.value)
: null;

const filteredRunContext = runContext?.filter(
(item) => item.Errors && item.Errors.length > 0
);

const connectionsMap =
connectionsData?.connections?.reduce(
(acc, connection) => {
acc[connection.id] = connection;
return acc;
},
{} as Record<string, Connection>
) ?? {};

return (
<div>
{filteredRunContext && filteredRunContext.length > 0 && (
<ScrollArea className="h-[400px] w-full rounded-md border">
{filteredRunContext.map((connectionError) => (
<div key={connectionError.ConnectionId} className="p-4">
<Alert className="border-red-500">
<div className="flex flex-row items-center gap-2">
<IoAlertCircleOutline className="h-6 w-6" />
<AlertTitle className="text-lg">
Connection:{' '}
{connectionsMap[connectionError.ConnectionId]?.name}
<span className="text-muted-foreground text-sm pl-4">
{connectionError.ConnectionId}
</span>
</AlertTitle>
</div>
<AlertDescription>
<h2 className="text-md font-semibold text-muted-foreground mt-2">
Schema Initialization Errors
</h2>
<Accordion type="single" collapsible className="w-full">
{connectionError.Errors.map((error, errorIdx) => (
<AccordionItem value={`item-${errorIdx}`} key={errorIdx}>
<AccordionTrigger className="text-left">
<div className="font-medium">{error.Error}</div>
</AccordionTrigger>
<AccordionContent>
<div className="space-y-2">
<div className="rounded-md bg-muted p-3">
<p className="font-medium">Statement:</p>
<pre className="mt-2 whitespace-pre-wrap text-sm">
{error.Statement}
</pre>
</div>
</div>
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</AlertDescription>
</Alert>
</div>
))}
</ScrollArea>
)}
</div>
);
}
8 changes: 8 additions & 0 deletions frontend/apps/web/app/(mgmt)/[account]/runs/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { toast } from 'sonner';
import { format as formatSql } from 'sql-formatter';
import yaml from 'yaml';
import JobRunStatus from '../components/JobRunStatus';
import JobRunActivityErrors from './components/JobRunActivityErrors';
import JobRunActivityTable from './components/JobRunActivityTable';
import JobRunLogs from './components/JobRunLogs';

Expand Down Expand Up @@ -341,6 +342,13 @@ export default function Page({ params }: PageProps): ReactElement {
}
})}
</div>
<div className="space-y-4">
<JobRunActivityErrors
jobRunId={id}
jobId={jobRun?.jobId ?? ''}
accountId={accountId}
/>
</div>
{!isSystemAppConfigDataLoading &&
systemAppConfigData?.enableRunLogs && (
<div>
Expand Down
40 changes: 40 additions & 0 deletions frontend/apps/web/components/providers/query-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';
import { getErrorMessage } from '@/util/util';
import { Code, ConnectError } from '@neosync/sdk';
import {
isServer,
QueryCache,
Expand Down Expand Up @@ -50,3 +51,42 @@ export default function TanstackQueryProvider(props: Props): ReactElement {
</QueryClientProvider>
);
}

// This is a query provider that ignores 404 errors.
export function TanstackQueryProviderIgnore404Errors(
props: Props
): ReactElement {
const { children } = props;

if (isServer) {
const client = new QueryClient({
defaultOptions: {
queries: { staleTime: 60 * 1000 },
},
});
return (
<QueryClientProvider client={client}>{children}</QueryClientProvider>
);
}

const browserQueryClient404 = new QueryClient({
queryCache: new QueryCache({
// good blog here: https://tkdodo.eu/blog/react-query-error-handling
onError(error, query) {
if (error instanceof ConnectError && error.code !== Code.NotFound) {
toast.error('Something went wrong', {
description: getErrorMessage(error),
id: query.queryKey.toString(),
});
}
},
}),
defaultOptions: {},
});

return (
<QueryClientProvider client={browserQueryClient404}>
{children}
</QueryClientProvider>
);
}

0 comments on commit 7710aa2

Please sign in to comment.