diff --git a/.changeset/lucky-beers-report.md b/.changeset/lucky-beers-report.md new file mode 100644 index 000000000..2874c0f56 --- /dev/null +++ b/.changeset/lucky-beers-report.md @@ -0,0 +1,5 @@ +--- +'@powersync/diagnostics-app': patch +--- + +Improved query parameter warnings and limits diff --git a/tools/diagnostics-app/src/app/views/sync-diagnostics.tsx b/tools/diagnostics-app/src/app/views/sync-diagnostics.tsx index 52aee6ec2..79725f940 100644 --- a/tools/diagnostics-app/src/app/views/sync-diagnostics.tsx +++ b/tools/diagnostics-app/src/app/views/sync-diagnostics.tsx @@ -8,8 +8,9 @@ import { Spinner } from '@/components/ui/spinner'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { NewStreamSubscription } from '@/components/widgets/NewStreamSubscription'; import { StreamsTable } from '@/components/widgets/StreamsTable'; -import { formatBytes } from '@/lib/utils'; +import { cn, formatBytes } from '@/lib/utils'; import { clearData, connector, db, sync, useSyncStatus } from '@/library/powersync/ConnectionManager'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { decodeTokenPayload, getTokenUserId } from '@/library/powersync/TokenConnector'; import { useQueryClient, useQuery as useTanstackQuery } from '@tanstack/react-query'; import { ChevronDown, ChevronUp, Eye, Info } from 'lucide-react'; @@ -90,6 +91,17 @@ const syncDiagnosticsKeys = { /** When total_operations exceeds row_count by this factor, we show a warning that bucket history has accumulated and compacting may help. This is an abritrary threshold and indicates significant history buildup.*/ const BUCKET_HISTORY_THRESHOLD = 3; +/** + * Default server-side limit for both the "too many buckets" and "too many parameter query results" + * limits (both reported as error PSYNC_S2305). These are two distinct limits that often coincide + * but can differ: + * - Duplicate parameter query results count individually toward the parameter result limit, + * but are de-duplicated in the bucket count. + * - Non-partitioning queries count 1 toward the bucket limit but not toward the parameter result limit. + * The default is 1000 but can be configured on the server. + */ +const DEFAULT_SYNC_LIMIT = 1000; + interface SyncStats { bucketRows: any[] | null; tableRows: any[] | null; @@ -222,6 +234,7 @@ export default function SyncDiagnosticsPage() { const totals = { buckets: rows.length, + parameterized_buckets: rows.filter((row) => !row.name.endsWith('[]')).length, row_count: rows.reduce((total, row) => total + row.row_count, 0), downloaded_operations: rows.reduce((total, row) => total + row.downloaded_operations, 0), total_operations: rows.reduce((total, row) => total + row.total_operations, 0), @@ -272,7 +285,44 @@ export default function SyncDiagnosticsPage() { - Buckets + + + + + + Buckets + + + + + Two separate limits apply (both PSYNC_S2305, default {DEFAULT_SYNC_LIMIT.toLocaleString()}{' '} + each): bucket count and parameter query results. +
+ Global buckets count only toward bucket count. Parameter query buckets (in either{' '} + + Sync Rules + {' '} + or{' '} + + Sync Streams + + ) count toward both, but are de-duplicated client-side, so the server's parameter result count + may be higher. +
+
+
+
+
Total Rows Downloaded Ops Total Ops @@ -284,7 +334,22 @@ export default function SyncDiagnosticsPage() {
- {totals.buckets} + + = 900 ? 'text-destructive' : totals.buckets >= 800 ? 'text-amber-600' : '' + )} + > + {totals.buckets.toLocaleString()} + + + / {DEFAULT_SYNC_LIMIT.toLocaleString()} (default) + +
+ {totals.parameterized_buckets.toLocaleString()} parameterized,{' '} + {(totals.buckets - totals.parameterized_buckets).toLocaleString()} global +
+
{totals.row_count.toLocaleString()} {totals.downloaded_operations.toLocaleString()} {totals.total_operations.toLocaleString()} @@ -300,7 +365,22 @@ export default function SyncDiagnosticsPage() {
Buckets
-
{totals.buckets}
+
+ = 900 ? 'text-destructive' : totals.buckets >= 800 ? 'text-amber-600' : '' + )} + > + {totals.buckets.toLocaleString()} + + + / {DEFAULT_SYNC_LIMIT.toLocaleString()} (default) + +
+ {totals.parameterized_buckets.toLocaleString()} parameterized,{' '} + {(totals.buckets - totals.parameterized_buckets).toLocaleString()} global +
+
Total Rows
@@ -358,7 +438,8 @@ export default function SyncDiagnosticsPage() { variant="ghost" size="sm" className="h-7 gap-1.5 text-muted-foreground" - onClick={() => setShowTokenDialog(true)}> + onClick={() => setShowTokenDialog(true)} + > View Token @@ -401,7 +482,8 @@ export default function SyncDiagnosticsPage() { variant="outline" onClick={() => { clearData(); - }}> + }} + > Clear & Redownload @@ -420,12 +502,35 @@ export default function SyncDiagnosticsPage() { href="https://docs.powersync.com/maintenance-ops/compacting-buckets" target="_blank" rel="noopener noreferrer" - className="underline hover:text-foreground"> + className="underline hover:text-foreground" + > Learn about compacting )} + {totals.buckets >= 800 && ( + = 900 ? 'border-destructive/50' : 'border-amber-500/50')}> + = 900 ? 'text-destructive' : 'text-amber-600')} /> + + = 900 ? 'text-destructive' : 'text-amber-600')}> + {totals.buckets >= 900 ? 'Critical: ' : 'Warning: '} + + {totals.buckets.toLocaleString()} of {DEFAULT_SYNC_LIMIT.toLocaleString()} buckets used (PSYNC_S2305, + default limit). {totals.parameterized_buckets.toLocaleString()} are parameterized - at least that many + parameter query results on the server. Review your Sync Config to reduce buckets and parameter query + results for this user.{' '} + + For troubleshooting steps, see the docs + + + + )}
@@ -511,7 +616,8 @@ function TruncatedTablesList({ tables }: { tables: string }) { e.stopPropagation(); setExpanded(!expanded); }} - className="inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"> + className="inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors" + > {expanded ? ( <>