diff --git a/ui/app/mirrors/edit/[mirrorId]/aggregatedCountsByInterval.ts b/ui/app/mirrors/edit/[mirrorId]/aggregatedCountsByInterval.ts
index 1da7ed132e..bdadb85b8d 100644
--- a/ui/app/mirrors/edit/[mirrorId]/aggregatedCountsByInterval.ts
+++ b/ui/app/mirrors/edit/[mirrorId]/aggregatedCountsByInterval.ts
@@ -21,17 +21,13 @@ function aggregateCountsByInterval(
timeUnit = 'YYYY-MM';
break;
case 'day':
+ case 'week':
timeUnit = 'YYYY-MM-DD';
break;
case '1min':
- timeUnit = 'YYYY-MM-DD HH:mm';
- break;
case '5min':
timeUnit = 'YYYY-MM-DD HH:mm';
break;
- case 'week':
- timeUnit = 'YYYY-MM-DD';
- break;
default:
throw new Error('Invalid interval provided');
}
diff --git a/ui/app/mirrors/edit/[mirrorId]/cdc.tsx b/ui/app/mirrors/edit/[mirrorId]/cdc.tsx
index 36b7d6582e..14b80d54c9 100644
--- a/ui/app/mirrors/edit/[mirrorId]/cdc.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/cdc.tsx
@@ -96,7 +96,7 @@ type SnapshotStatusProps = {
status: SnapshotStatus;
};
-const ROWS_PER_PAGE = 6;
+const ROWS_PER_PAGE = 10;
export const SnapshotStatusTable = ({ status }: SnapshotStatusProps) => {
const allRows = status.clones.map(summarizeTableClone);
const [sortField, setSortField] = useState<
@@ -107,9 +107,10 @@ export const SnapshotStatusTable = ({ status }: SnapshotStatusProps) => {
const startRow = (currentPage - 1) * ROWS_PER_PAGE;
const endRow = startRow + ROWS_PER_PAGE;
- const [displayedRows, setDisplayedRows] = useState(
+ const [displayedRows, setDisplayedRows] = useState(() =>
allRows.slice(startRow, endRow)
);
+
const handlePrevPage = () => {
if (currentPage > 1) {
setCurrentPage(currentPage - 1);
@@ -186,7 +187,6 @@ export const SnapshotStatusTable = ({ status }: SnapshotStatusProps) => {
(val?.value as 'cloneStartTime' | 'avgTimePerPartition') ??
'cloneStartTime';
setSortField(sortVal);
- handleSort(sortVal);
}}
value={{
value: sortField,
diff --git a/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx b/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx
index 21ac59d4c8..f52450ade0 100644
--- a/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/cdcDetails.tsx
@@ -1,4 +1,5 @@
'use client';
+import MirrorInfo from '@/components/MirrorInfo';
import PeerButton from '@/components/PeerComponent';
import TimeLabel from '@/components/TimeComponent';
import { FlowConnectionConfigs } from '@/grpc_generated/flow';
@@ -7,7 +8,8 @@ import { Badge } from '@/lib/Badge';
import { Icon } from '@/lib/Icon';
import { Label } from '@/lib/Label';
import moment from 'moment';
-import CdcGraph from './cdcGraph';
+import MirrorValues from './configValues';
+import TablePairs from './tablePairs';
type SyncStatusRow = {
batchId: number;
@@ -113,109 +115,19 @@ function CdcDetails({ syncs, createdAt, mirrorConfig }: props) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
- Source Table
- |
-
- Destination Table
- |
-
-
-
- {tablesSynced?.map((table) => (
-
-
- {table.sourceTableIdentifier}
- |
-
- {table.destinationTableIdentifier}
- |
-
- ))}
-
-
+
+
>
);
}
-function numberWithCommas(x: Number): string {
+export function numberWithCommas(x: any): string {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
diff --git a/ui/app/mirrors/edit/[mirrorId]/cdcGraph.tsx b/ui/app/mirrors/edit/[mirrorId]/cdcGraph.tsx
index 94ea57403d..6c5e9988c1 100644
--- a/ui/app/mirrors/edit/[mirrorId]/cdcGraph.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/cdcGraph.tsx
@@ -1,3 +1,4 @@
+'use client';
import { Label } from '@/lib/Label';
import moment from 'moment';
import { useEffect, useState } from 'react';
@@ -11,16 +12,6 @@ type SyncStatusRow = {
import aggregateCountsByInterval from './aggregatedCountsByInterval';
-const aggregateTypeMap: { [key: string]: string } = {
- '15min': ' 15 mins',
- '5min': '5 mins',
- '1min': '1 min',
- hour: 'Hour',
- day: 'Day',
- month: 'Month',
- week: 'Week',
-};
-
function CdcGraph({ syncs }: { syncs: SyncStatusRow[] }) {
let [aggregateType, setAggregateType] = useState('hour');
const initialCount: [string, number][] = [];
diff --git a/ui/app/mirrors/edit/[mirrorId]/configValues.ts b/ui/app/mirrors/edit/[mirrorId]/configValues.ts
new file mode 100644
index 0000000000..7f5172d1cd
--- /dev/null
+++ b/ui/app/mirrors/edit/[mirrorId]/configValues.ts
@@ -0,0 +1,57 @@
+import { FlowConnectionConfigs, QRepSyncMode } from '@/grpc_generated/flow';
+
+const syncModeToLabel = (mode: QRepSyncMode) => {
+ switch (mode) {
+ case QRepSyncMode.QREP_SYNC_MODE_STORAGE_AVRO:
+ return 'AVRO';
+ case QRepSyncMode.QREP_SYNC_MODE_MULTI_INSERT:
+ return 'Copy with Binary';
+ default:
+ return 'AVRO';
+ }
+};
+const MirrorValues = (mirrorConfig: FlowConnectionConfigs | undefined) => {
+ return [
+ {
+ value: `${mirrorConfig?.maxBatchSize} rows`,
+ label: 'Pull Batch Size',
+ },
+ {
+ value: `${mirrorConfig?.snapshotNumRowsPerPartition} rows`,
+ label: 'Snapshot Rows Per Partition',
+ },
+ {
+ value: `${mirrorConfig?.snapshotNumTablesInParallel} table(s)`,
+ label: 'Snapshot Tables In Parallel',
+ },
+ {
+ value: `${mirrorConfig?.snapshotMaxParallelWorkers} worker(s)`,
+ label: 'Snapshot Parallel Tables',
+ },
+ {
+ value: `${syncModeToLabel(mirrorConfig?.cdcSyncMode!)} mode`,
+ label: 'CDC Sync Mode',
+ },
+ {
+ value: `${syncModeToLabel(mirrorConfig?.snapshotSyncMode!)} mode`,
+ label: 'Snapshot Sync Mode',
+ },
+ {
+ value: `${
+ mirrorConfig?.cdcStagingPath?.length
+ ? mirrorConfig?.cdcStagingPath
+ : 'Local'
+ }`,
+ label: 'CDC Staging Path',
+ },
+ {
+ value: `${
+ mirrorConfig?.snapshotStagingPath?.length
+ ? mirrorConfig?.snapshotStagingPath
+ : 'Local'
+ }`,
+ label: 'Snapshot Staging Path',
+ },
+ ];
+};
+export default MirrorValues;
diff --git a/ui/app/mirrors/edit/[mirrorId]/page.tsx b/ui/app/mirrors/edit/[mirrorId]/page.tsx
index 99a5168cee..756684b854 100644
--- a/ui/app/mirrors/edit/[mirrorId]/page.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/page.tsx
@@ -33,13 +33,6 @@ export default async function EditMirror({
return
No mirror status found!
;
}
- let syncStatusChild = <>>;
- if (mirrorStatus.cdcStatus) {
- syncStatusChild =
;
- } else {
- redirect(`/mirrors/status/qrep/${mirrorId}`);
- }
-
let createdAt = await prisma.flows.findFirst({
select: {
created_at: true,
@@ -61,6 +54,16 @@ export default async function EditMirror({
},
});
+ let syncStatusChild = <>>;
+ if (mirrorStatus.cdcStatus) {
+ let rowsSynced = syncs.reduce((acc, sync) => acc + sync.rows_in_batch, 0);
+ syncStatusChild = (
+
+ );
+ } else {
+ redirect(`/mirrors/status/qrep/${mirrorId}`);
+ }
+
const rows = syncs.map((sync) => ({
batchId: sync.id,
startTime: sync.start_time,
diff --git a/ui/app/mirrors/edit/[mirrorId]/syncStatus.tsx b/ui/app/mirrors/edit/[mirrorId]/syncStatus.tsx
index f1fea81f17..0a481241ca 100644
--- a/ui/app/mirrors/edit/[mirrorId]/syncStatus.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/syncStatus.tsx
@@ -1,11 +1,20 @@
import prisma from '@/app/utils/prisma';
+import { Label } from '@/lib/Label';
+import CdcGraph from './cdcGraph';
import { SyncStatusTable } from './syncStatusTable';
+function numberWithCommas(x: Number): string {
+ return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+}
type SyncStatusProps = {
flowJobName: string | undefined;
+ rowsSynced: Number;
};
-export default async function SyncStatus({ flowJobName }: SyncStatusProps) {
+export default async function SyncStatus({
+ flowJobName,
+ rowsSynced,
+}: SyncStatusProps) {
if (!flowJobName) {
return
Flow job name not provided!
;
}
@@ -31,6 +40,20 @@ export default async function SyncStatus({ flowJobName }: SyncStatusProps) {
return (
+
+
+
+
+
+
+
+
+
+
+
+
);
diff --git a/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx b/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx
index fb4f6bfd9c..9b6ff1bb5b 100644
--- a/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx
@@ -48,7 +48,7 @@ function TimeWithDurationOrRunning({
}
}
-const ROWS_PER_PAGE = 6;
+const ROWS_PER_PAGE = 10;
const sortOptions = [
{ value: 'startTime', label: 'Start Time' },
{ value: 'endTime', label: 'End Time' },
@@ -143,7 +143,6 @@ export const SyncStatusTable = ({ rows }: SyncStatusTableProps) => {
(val?.value as 'startTime' | 'endTime' | 'numRows') ??
'startTime';
setSortField(sortVal);
- handleSort(sortVal);
}}
defaultValue={{ value: 'startTime', label: 'Start Time' }}
/>
diff --git a/ui/app/mirrors/edit/[mirrorId]/tablePairs.tsx b/ui/app/mirrors/edit/[mirrorId]/tablePairs.tsx
new file mode 100644
index 0000000000..24d2f37f80
--- /dev/null
+++ b/ui/app/mirrors/edit/[mirrorId]/tablePairs.tsx
@@ -0,0 +1,83 @@
+'use client';
+import SearchBar from '@/components/Search';
+import { TableMapping } from '@/grpc_generated/flow';
+import { useState } from 'react';
+
+const TablePairs = ({ tables }: { tables?: TableMapping[] }) => {
+ const [shownTables, setShownTables] = useState
(
+ tables
+ );
+ if (tables)
+ return (
+ <>
+
+
+ tables.filter((table: TableMapping) => {
+ return (
+ table.sourceTableIdentifier.includes(query) ||
+ table.destinationTableIdentifier.includes(query)
+ );
+ })
+ }
+ />
+
+
+
+
+
+ Source Table
+ |
+
+ Destination Table
+ |
+
+
+
+ {shownTables?.map((table) => (
+
+
+ {table.sourceTableIdentifier}
+ |
+
+ {table.destinationTableIdentifier}
+ |
+
+ ))}
+
+
+ >
+ );
+};
+
+export default TablePairs;
diff --git a/ui/components/DropDialog.tsx b/ui/components/DropDialog.tsx
index f3de3c283f..2de31d9c55 100644
--- a/ui/components/DropDialog.tsx
+++ b/ui/components/DropDialog.tsx
@@ -79,7 +79,7 @@ export const DropDialog = ({
return (