reserve method

Future<Reservation> reserve(
  1. PeerId relayPeerId
)

Reserves a slot on a relay.

Implementation

Future<Reservation> reserve(PeerId relayPeerId) async {
  // Notify metrics observer that reservation is starting
  final reservationStartTime = DateTime.now();
  metricsObserver?.onReservationRequested(relayPeerId, reservationStartTime);

  try {
    // Open a stream to the relay using Hop protocol
    // 'this.host' or simply 'host' refers to the host field of CircuitV2Client
    final stream = await host.newStream(
        relayPeerId, [CircuitV2Protocol.protoIDv2Hop], Context());

    // Set deadline for the entire operation, including stream opening, write, and read.
    // Dart's newStream doesn't have a per-operation deadline like Go's s.SetDeadline.
    // We'll rely on the timeout for the Future.
    final reservation = await _reserveStream(stream, relayPeerId)
        .timeout(reserveTimeout, onTimeout: () {
      stream.close(); // Ensure stream is closed on timeout
      throw ReservationError(
          status: pb.Status.CONNECTION_FAILED,
          reason: 'reservation timed out');
    });

    // Notify metrics observer of successful reservation
    final reservationCompleteTime = DateTime.now();
    final reservationDuration =
        reservationCompleteTime.difference(reservationStartTime);
    metricsObserver?.onReservationCompleted(
      relayPeerId,
      reservationStartTime,
      reservationCompleteTime,
      reservationDuration,
      true,
      null,
    );

    return reservation;
  } catch (e) {
    // Notify metrics observer of failed reservation
    final reservationCompleteTime = DateTime.now();
    final reservationDuration =
        reservationCompleteTime.difference(reservationStartTime);
    metricsObserver?.onReservationCompleted(
      relayPeerId,
      reservationStartTime,
      reservationCompleteTime,
      reservationDuration,
      false,
      e.toString(),
    );
    rethrow;
  }
}