performRpc method

Future<String> performRpc(
  1. PerformRpcParams params
)

Initiate an RPC call to a remote participant. @param params - RPC call parameters. @returns A promise that resolves with the response payload or rejects with an error. @throws Error on failure. Details in message.

Implementation

Future<String> performRpc(PerformRpcParams params) async {
  final requestId = Uuid().v4();
  final completer = Completer<String>();

  final maxRoundTripLatency = Duration(seconds: 7);
  final minEffectiveTimeout = const Duration(milliseconds: 1000);

  try {
    final effectiveTimeout = Duration(
      milliseconds: (params.responseTimeoutMs.inMilliseconds - maxRoundTripLatency.inMilliseconds)
          .clamp(minEffectiveTimeout.inMilliseconds, double.infinity)
          .toInt(),
    );
    await publishRpcRequest(
      destinationIdentity: params.destinationIdentity,
      requestId: requestId,
      method: params.method,
      payload: params.payload,
      responseTimeout: effectiveTimeout,
      version: kRpcVesion,
    );

    final ackTimer = Timer(maxRoundTripLatency, () {
      completer.completeError(RpcError.builtIn(RpcError.connectionTimeout));
      _pendingResponses.remove(requestId);
    });

    _pendingAcks[requestId] = (id) {
      ackTimer.cancel();
    };

    final responseTimer = Timer(params.responseTimeoutMs, () {
      completer.completeError(RpcError.builtIn(RpcError.responseTimeout));
      _pendingResponses.remove(requestId);
    });

    _pendingResponses[requestId] = (String? response, RpcError? error) {
      responseTimer.cancel();
      if (error != null) {
        completer.completeError(error);
      } else {
        completer.complete(response!);
      }
      ackTimer.cancel();
      _pendingAcks.remove(requestId);
    };
  } catch (e) {
    if (!completer.isCompleted) {
      completer.completeError(e);
    }
  }

  return completer.future;
}