diff --git a/packages/discovery-provider/plugins/pedalboard/apps/relay/src/coreRelay.ts b/packages/discovery-provider/plugins/pedalboard/apps/relay/src/coreRelay.ts index f1d0130a516..3e5525b847f 100644 --- a/packages/discovery-provider/plugins/pedalboard/apps/relay/src/coreRelay.ts +++ b/packages/discovery-provider/plugins/pedalboard/apps/relay/src/coreRelay.ts @@ -20,29 +20,89 @@ import { } from './audiusd-sdk/core/v1/types_pb.js' type ClientType = 'grpc' | 'connect' -let activeClient: { type: ClientType; client: Client } | null = null -async function initializeClients(logger: pino.Logger): Promise { - if (activeClient) return true +interface ClientInfo { + type: ClientType + client: Client + lastSuccessfulPing: number +} + +const clients: { + grpc?: ClientInfo + connect?: ClientInfo +} = {} + +let activeClient: ClientInfo | null = null + +async function pingClient(clientInfo: ClientInfo): Promise { + try { + if (clientInfo.type === 'grpc') { + await (clientInfo.client as Client).ping(create(GrpcPingRequestSchema, {})) + } else { + await (clientInfo.client as Client).ping(create(PingRequestSchema, {})) + } + clientInfo.lastSuccessfulPing = Date.now() + return true + } catch (e) { + return false + } +} + +async function updateActiveClient(logger: pino.Logger) { + // Ping both clients + const results = await Promise.all([ + clients.grpc && pingClient(clients.grpc), + clients.connect && pingClient(clients.connect) + ]) + + // Update active client based on most recent successful ping + const grpcSuccess = results[0] + const connectSuccess = results[1] + + if (grpcSuccess && connectSuccess) { + // Use the client with the most recent successful ping + activeClient = clients.grpc!.lastSuccessfulPing > clients.connect!.lastSuccessfulPing + ? clients.grpc! + : clients.connect! + } else if (grpcSuccess) { + activeClient = clients.grpc! + } else if (connectSuccess) { + activeClient = clients.connect! + } else { + activeClient = null + } + if (activeClient) { + logger.info(`Using ${activeClient.type} client for transactions`) + } else { + logger.error('No clients are currently available') + } +} + +async function initializeClients(logger: pino.Logger): Promise { const config = readConfig() - // Try GRPC client first + // Try GRPC client try { const grpcTransport = createGrpcTransport({ baseUrl: config.coreEndpoint, useBinaryFormat: true }) const grpcClient = createClient(Protocol, grpcTransport) - await grpcClient.ping(create(GrpcPingRequestSchema, {})) - activeClient = { type: 'grpc', client: grpcClient } - logger.info('Successfully connected using gRPC client') - return true + const grpcInfo: ClientInfo = { + type: 'grpc', + client: grpcClient, + lastSuccessfulPing: 0 + } + if (await pingClient(grpcInfo)) { + clients.grpc = grpcInfo + logger.info('Successfully connected using gRPC client') + } } catch (e) { - logger.warn({ err: e }, 'gRPC client ping failed, trying Connect client') + logger.warn({ err: e }, 'gRPC client initialization failed') } - // Try Connect client if GRPC failed + // Try Connect client try { const connectTransport = createConnectTransport({ baseUrl: config.coreEndpoint, @@ -50,14 +110,30 @@ async function initializeClients(logger: pino.Logger): Promise { useBinaryFormat: true }) const connectClient = createClient(CoreService, connectTransport) - await connectClient.ping(create(PingRequestSchema, {})) - activeClient = { type: 'connect', client: connectClient } - logger.info('Successfully connected using Connect client') - return true + const connectInfo: ClientInfo = { + type: 'connect', + client: connectClient, + lastSuccessfulPing: 0 + } + if (await pingClient(connectInfo)) { + clients.connect = connectInfo + logger.info('Successfully connected using Connect client') + } } catch (e) { - logger.error({ err: e }, 'Both client connection attempts failed') - return false + logger.warn({ err: e }, 'Connect client initialization failed') } + + // Update active client based on ping results + await updateActiveClient(logger) + + // Start periodic ping checks if at least one client is available + if (activeClient) { + setInterval(() => updateActiveClient(logger), 30000) // Check every 30 seconds + return true + } + + logger.error('Failed to initialize any clients') + return false } type CoreRelayResponse = {