queryServerCapacity method

Future<ServerCapacity?> queryServerCapacity(
  1. PeerId serverId
)

Query server capacity (with caching)

Implementation

Future<ServerCapacity?> queryServerCapacity(PeerId serverId) async {
  final cacheKey = serverId.toString();

  // Check cache first
  final cached = _capacityCache[cacheKey];
  if (cached != null) {
    _logger.fine('Using cached capacity for ${serverId.toString().substring(0, 12)}...');
    return cached;
  }

  try {
    // Open stream and query capacity via MMA (admin) protocol
    final context = Context();
    final stream = await host.newStream(
      serverId,
      [adminProtocolId],
      context,
    );

    // Create query capacity request
    final request = QueryCapacityRequest();
    final requestBytes = AdminFrame.encodeRequest(request);

    // Send with length prefix
    final lengthBytes = ByteData(4)..setUint32(0, requestBytes.length);
    final combined = Uint8List(4 + requestBytes.length);
    combined.setRange(0, 4, lengthBytes.buffer.asUint8List());
    combined.setRange(4, 4 + requestBytes.length, requestBytes);

    await stream.write(combined);

    // Read response length
    final responseLengthBytes = await stream.read(4);
    if (responseLengthBytes.length < 4) {
      throw StateError('Failed to read response length');
    }

    final responseLength = responseLengthBytes.buffer.asByteData().getUint32(0);

    // Read response
    final responseBytes = await stream.read(responseLength);
    if (responseBytes.length < responseLength) {
      throw StateError('Failed to read complete response');
    }

    final response = AdminFrame.decodeResponse(responseBytes);
    await stream.close();

    if (!response.success || response.data == null) {
      _logger.warning('Server capacity query failed: ${response.errorMessage}');
      return null;
    }

    final capacity = ServerCapacity.fromJson(response.data as Map<String, dynamic>);

    // Cache the result
    _capacityCache[cacheKey] = capacity;

    // Schedule cache cleanup
    Future.delayed(_capacityCacheDuration, () {
      _capacityCache.remove(cacheKey);
    });

    return capacity;

  } catch (e) {
    _logger.warning('Failed to query server capacity: $e');
    return null;
  }
}