import { connectToISocketRPCServer, } from "./client.js";
export class AutoConnectingRpcClient {
    superblocksBaseUrl;
    authToken;
    _tracer;
    tokenManager;
    _logger;
    _rpcClient = null;
    _isShuttingDown = false;
    _activeOperations = 0;
    _socketCloseCode;
    constructor(superblocksBaseUrl, authToken, _tracer, tokenManager, _logger) {
        this.superblocksBaseUrl = superblocksBaseUrl;
        this.authToken = authToken;
        this._tracer = _tracer;
        this.tokenManager = tokenManager;
        this._logger = _logger;
        this.tokenManager.on("tokenUpdated", (event) => {
            this.getLogger().info(`[ai-service] Token refresh triggered socket reconnection`);
            void this.close().then(() => {
                this.authToken = event.token;
                void this.getRpcClient();
            });
        });
    }
    getLogger() {
        return this._logger;
    }
    get socketCloseCode() {
        return this._socketCloseCode;
    }
    async getRpcClient() {
        if (this._isShuttingDown) {
            throw new Error("RPC client is shutting down");
        }
        if (!this._rpcClient) {
            let connectionAttempts = 0;
            while (connectionAttempts < 3) {
                try {
                    // This can fail if the initial WS connection fails due to a network issue, so we retry up to 3 times
                    this._rpcClient = await connectToISocketRPCServer({
                        superblocksBaseUrl: this.superblocksBaseUrl,
                        token: this.authToken,
                        tracer: this._tracer,
                        onClose: (event) => {
                            this.getLogger().info(`[rpc-client] socket closed with code: ${event.code}`);
                            this._socketCloseCode = event.code;
                            this._rpcClient = null;
                        },
                    });
                }
                catch (error) {
                    connectionAttempts++;
                    console.error(`Failed on attempt ${connectionAttempts} to get connection:`, error.message);
                }
                if (this._rpcClient) {
                    break;
                }
                // Wait 5 seconds before retrying
                await new Promise((resolve) => setTimeout(resolve, 5000));
            }
        }
        if (!this._rpcClient) {
            throw new Error("Failed to connect to socket after 3 attempts");
        }
        return this._rpcClient;
    }
    /**
     * Executes an RPC operations with lifecycle management.
     */
    async call(operation) {
        if (this._isShuttingDown) {
            throw new Error("RPC client is shutting down");
        }
        this._activeOperations++;
        try {
            const client = await this.getRpcClient();
            return await operation(client);
        }
        finally {
            this._activeOperations--;
        }
    }
    async close() {
        this._isShuttingDown = true;
        // Wait for active operations to finish with timeout
        const maxWaitTime = 5_000;
        const startTime = Date.now();
        while (this._activeOperations > 0 && Date.now() - startTime < maxWaitTime) {
            await new Promise((resolve) => setTimeout(resolve, 100));
        }
        if (this._activeOperations > 0) {
            this.getLogger().warn(`[rpc-client] Forced shutdown of RPC client with ${this._activeOperations} active operations`);
        }
        if (this._rpcClient) {
            await this._rpcClient.close();
            this._rpcClient = null;
        }
        this._isShuttingDown = false;
    }
}
//# sourceMappingURL=index.js.map