/** * Federation Queries API Client * Handles federated query requests to remote instances */ import { apiGet, apiPost } from "./client"; /** * Federation message status (matches backend enum) */ export enum FederationMessageStatus { PENDING = "PENDING", DELIVERED = "DELIVERED", FAILED = "FAILED", } /** * Query message details */ export interface QueryMessageDetails { id: string; workspaceId: string; connectionId: string; messageType: string; messageId: string; correlationId?: string; query?: string; response?: unknown; status: FederationMessageStatus; error?: string; createdAt: string; updatedAt: string; deliveredAt?: string; } /** * Send query request */ export interface SendQueryRequest { connectionId: string; query: string; context?: Record; } /** * Send a federated query to a remote instance */ export async function sendFederatedQuery( connectionId: string, query: string, context?: Record ): Promise { const request: SendQueryRequest = { connectionId, query, }; if (context) { request.context = context; } return apiPost("/api/v1/federation/query", request); } /** * Fetch all query messages for the workspace */ export async function fetchQueryMessages( status?: FederationMessageStatus ): Promise { const params = new URLSearchParams(); if (status) { params.append("status", status); } const queryString = params.toString(); const endpoint = queryString ? `/api/v1/federation/queries?${queryString}` : "/api/v1/federation/queries"; return apiGet(endpoint); } /** * Fetch a single query message */ export async function fetchQueryMessage(messageId: string): Promise { return apiGet(`/api/v1/federation/queries/${messageId}`); } /** * Poll for query response with timeout * @param messageId - The message ID to poll for * @param options - Polling options * @returns The query message details when delivered or failed * @throws Error if timeout is reached or message fails */ export async function pollForQueryResponse( messageId: string, options?: { pollInterval?: number; // milliseconds between polls (default: 500) timeout?: number; // maximum time to wait in milliseconds (default: 30000) } ): Promise { const pollInterval = options?.pollInterval ?? 500; const timeout = options?.timeout ?? 30000; const startTime = Date.now(); // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition while (true) { // Check if timeout has been reached if (Date.now() - startTime > timeout) { throw new Error(`Query timeout after ${String(timeout)}ms`); } // Fetch the message const message = await fetchQueryMessage(messageId); // Check if the message is complete if (message.status === FederationMessageStatus.DELIVERED) { return message; } if (message.status === FederationMessageStatus.FAILED) { throw new Error(message.error ?? "Query failed"); } // Wait before polling again await new Promise((resolve) => setTimeout(resolve, pollInterval)); } }