Skip to content

Commit 5d08203

Browse files
committed
docs: remove warning and add TODO
Signed-off-by: Rob Walworth <[email protected]>
1 parent f93a1d1 commit 5d08203

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

Sources/Hiero/Client/ChannelBalancer.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,20 @@ import SwiftProtobuf
2020
/// - Complexity of maintaining accurate per-channel metrics
2121
/// - Race conditions in concurrent request tracking
2222
///
23+
/// ## Timeout Handling
24+
/// This balancer does not enforce per-request timeouts. Timeout protection is
25+
/// provided at the execution layer via `ExponentialBackoff.maxElapsedTime` and
26+
/// `Backoff.requestTimeout`, which prevent indefinite hangs during retries.
27+
///
28+
/// - TODO: Implement GRPC-level timeouts using `Backoff.grpcTimeout`.
29+
/// To add this functionality, update `Execute.applyGrpcHeader()` to accept
30+
/// a timeout parameter and configure `CallOptions.timeLimit`. This would provide
31+
/// finer-grained timeout control for individual GRPC calls.
32+
///
2333
/// ## Related Types
2434
/// - `NodeConnection` - Uses ChannelBalancer for node-level load balancing
2535
/// - `MirrorNetwork` - Uses ChannelBalancer for mirror node distribution
26-
///
27-
/// - Warning: If a request to a non-existent host never returns, the system may hang.
28-
/// Consider implementing timeout handling at a higher level.
36+
/// - `Backoff` - Contains grpcTimeout field for future GRPC-level timeout support
2937
internal final class ChannelBalancer: GRPCChannel {
3038
// MARK: - Properties
3139

@@ -42,12 +50,16 @@ internal final class ChannelBalancer: GRPCChannel {
4250
/// - Parameters:
4351
/// - eventLoop: The event loop for channel operations
4452
/// - targetSecurityPairs: Array of connection targets paired with their security configurations
53+
///
54+
/// - Precondition: GRPC channel pool creation must succeed. If it fails, this is a
55+
/// programming error and the application should crash rather than continue with invalid state.
4556
internal init(
4657
eventLoop: EventLoop,
4758
targetSecurityPairs: [(GRPC.ConnectionTarget, GRPCChannelPool.Configuration.TransportSecurity)]
4859
) {
4960
self.eventLoop = eventLoop
5061
self.channels = targetSecurityPairs.map { (target, security) in
62+
// Crash intentionally if channel creation fails - no recovery possible at initialization
5163
try! GRPCChannelPool.with(target: target, transportSecurity: security, eventLoopGroup: eventLoop)
5264
}
5365
}

Sources/Hiero/Client/Client.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,10 @@ public final class Client: Sendable {
334334
public static func fromConfig(_ config: String) throws -> Self {
335335
let configData: ClientConfig
336336
do {
337-
configData = try JSONDecoder().decode(ClientConfig.self, from: config.data(using: .utf8)!)
337+
guard let data = config.data(using: .utf8) else {
338+
throw HError.basicParse("Invalid UTF-8 in configuration string")
339+
}
340+
configData = try JSONDecoder().decode(ClientConfig.self, from: data)
338341
} catch let error as DecodingError {
339342
throw HError.basicParse(String(describing: error))
340343
}

Sources/Hiero/Client/NodeHealth.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ internal enum NodeHealth: Sendable {
116116

117117
// Apply exponential backoff
118118
var backoff = self.backoff
119-
let backoffInterval = backoff.next()!
119+
let backoffInterval = backoff.next()! // Safe: backoff has unlimited max elapses time (never returns nil)
120120
let healthyAt = now.adding(nanos: backoffInterval.nanoseconds)
121121

122122
self = .unhealthy(

0 commit comments

Comments
 (0)