LCOV - code coverage report
Current view: top level - dashql-app/src/connections - connection_replace.ts Coverage Total Hit
Test: DashQL 6e74948 Lines: 100.0 % 33 33
Test Date: 2026-11-06 17:46:50

            Line data    Source code
       1              : import { isHyperWasmConnection } from './connection_label.js';
       2              : import { isListedConnection, type ConnectionReferences, type ConnectionRegistry } from './connection_registry.js';
       3              : import type { ConnectionState } from './connection_state.js';
       4              : 
       5              : /// The connections that can replace a connection, grouped by their connector
       6              : export interface ConnectionReplaceCandidates {
       7              :     /// The connections of the same connector
       8              :     sameConnector: ConnectionState[];
       9              :     /// The connections of other connectors
      10              :     otherConnectors: ConnectionState[];
      11              : }
      12              : 
      13              : /// The connections that can replace a connection.
      14              : ///
      15              : /// Every other listed connection can, the user can't see the others. The connections of the same
      16              : /// connector come first, they are the likely replacements.
      17            1 : export function connectionReplaceCandidates(
      18            1 :     registry: Pick<ConnectionRegistry, 'connections'>,
      19            1 :     references: ConnectionReferences,
      20            1 :     sourceId: string,
      21            1 : ): ConnectionReplaceCandidates {
      22            1 :     const source = registry.connections.get(sourceId);
      23            1 :     const candidates: ConnectionReplaceCandidates = { sameConnector: [], otherConnectors: [] };
      24            1 :     if (source == null) return candidates;
      25            1 :     for (const [connectionId, connection] of registry.connections) {
      26            1 :         if (connectionId === sourceId || !isListedConnection(registry, references, connectionId)) continue;
      27            1 :         if (connection.connectorInfo.connectorType === source.connectorInfo.connectorType) {
      28            1 :             candidates.sameConnector.push(connection);
      29              :         } else {
      30            1 :             candidates.otherConnectors.push(connection);
      31              :         }
      32            1 :     }
      33            1 :     return candidates;
      34            1 : }
      35              : 
      36              : /// What keeps a connection from being replaced, null if it can be replaced.
      37              : ///
      38              : /// A replacement moves the scripts of every session to the other connection and removes the
      39              : /// connection afterwards. Everything that would leave it half done blocks it up front:
      40              : ///  - The embedded Hyper is the connection that sessions fall back to, it is never removed.
      41              : ///  - Running queries would lose the connection they run on.
      42              : ///  - A session whose script changed outside the app holds its writes, its file can't follow.
      43            1 : export function connectionReplaceBlocker(
      44            1 :     registry: Pick<ConnectionRegistry, 'connections'>,
      45            1 :     references: ConnectionReferences,
      46            1 :     sourceId: string,
      47            1 :     isSessionHeld: (sessionId: string) => boolean,
      48            1 : ): string | null {
      49            1 :     const source = registry.connections.get(sourceId);
      50            1 :     if (source == null) return 'Unknown connection';
      51            1 :     if (isHyperWasmConnection(source)) return 'Sessions fall back to it';
      52            1 :     const running = source.queriesActiveOrdered.length;
      53            1 :     if (running > 0) return `${running} ${running === 1 ? 'query' : 'queries'} running`;
      54            1 :     const held = references.sessionsOf(sourceId).filter(isSessionHeld).length;
      55            1 :     if (held > 0) return `${held} ${held === 1 ? 'session' : 'sessions'} changed outside the app`;
      56            1 :     const candidates = connectionReplaceCandidates(registry, references, sourceId);
      57            1 :     if (candidates.sameConnector.length + candidates.otherConnectors.length === 0) return 'No other connection';
      58            1 :     return null;
      59            1 : }
        

Generated by: LCOV version 2.0-1