import dotenv from "dotenv"; import { EXECUTION_HISTORY_FETCH_COUNT } from "../utils/constants"; dotenv.config({ quiet: true }); export class HaltExecutionError extends Error { constructor(message: string, public status?: number) { super(message); this.name = "HaltExecutionError"; } } export const runExecution = async ( execId: number, token: string, testDataOverwriteObject?: Record, queryParams?: { uploadFailedVideos?: string; retryCount?: number; threadLimit?: number; } ) => { const baseUrl = process.env.EXECUTIONS_SERVER_URL; const url = new URL(`/api/executions/run/${execId}`, baseUrl); const params: Record = { uploadVideo: queryParams?.uploadFailedVideos, retryCount: queryParams?.retryCount, threadLimit: queryParams?.threadLimit, }; for (const [key, value] of Object.entries(params)) { if (value !== undefined) { url.searchParams.set(key, String(value)); } } try { const body = { VIA_CRON: false, HEADLESS: true, NODE_ENV_BLINQ: process.env.NODE_ENV_BLINQ, RUN_AS_MOCK: false, testDataOverwriteObject, }; const response = await fetch(url.toString(), { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify(body), }); if (!response.ok) { let errorText: string | undefined; try { errorText = await response.text(); } catch { errorText = ""; } console.error("❌ Failed to start execution", { url: url.toString(), status: response.status, statusText: response.statusText, serverResponse: errorText, requestBody: body, }); throw new Error( `Execution start failed (status ${response.status}) – ${errorText}` ); } return await response.json(); } catch (error) { console.error("❌ Error running execution:", { error, url: url.toString(), }); return { error: error instanceof Error ? error.message : String(error), }; } }; export const getExecutionHistory = async ( count = EXECUTION_HISTORY_FETCH_COUNT ): Promise => { try { const baseUrl = `${process.env.EXECUTIONS_SERVER_URL + "/api/executions" }/executionHistory`; const url = new URL(baseUrl); url.searchParams.append("count", count.toString()); const response = await fetch(url.toString(), { method: "GET", headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.ACCESS_TOKEN}`, }, }); if (!response.ok) { const errText = await response.text(); throw new Error( `Failed to fetch execution history: ${response.status} ${errText}` ); } const data = await response.json(); if (!data.status || !Array.isArray(data.data)) { throw new Error("Invalid response from server"); } return data.data; } catch (error) { console.error("❌ Error fetching execution history:", error); return []; } }; export const haltExecution = async (instanceId: string) => { try { const response = await fetch( `${process.env.EXECUTIONS_SERVER_URL + "/api/executions" }/halt/${instanceId}`, { method: "POST", headers: { Authorization: `Bearer ${process.env.ACCESS_TOKEN}`, }, } ); if (!response.ok) { const contentType = response.headers.get("content-type"); let errorBody: any; if (contentType?.includes("application/json")) { errorBody = await response.json(); } else { errorBody = await response.text(); } const backendMessage = typeof errorBody === "string" ? errorBody : errorBody?.error || "Unknown error"; throw new HaltExecutionError(backendMessage, response.status); } } catch (error) { if (error instanceof HaltExecutionError) { throw error; } throw new HaltExecutionError( `Failed to connect to server: ${(error as any)?.message}` ); } }; export async function getStatus(executionInstanceId: string) { const baseUrl = `${process.env.EXECUTIONS_SERVER_URL + "/api/executions" }/status/${executionInstanceId}`; try { const response = await fetch(baseUrl, { method: "GET", headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.ACCESS_TOKEN}`, }, }); if (!response.ok) { const errText = await response.text(); throw new Error( `Failed to fetch execution status: ${response.status} ${errText}` ); } const data = await response.json(); return data; } catch (error) { console.error("❌ Error fetching execution status:", error); return null; } }