Skip to content

Commit be748ca

Browse files
Add and test the Listendpoint limit
1 parent 353acff commit be748ca

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

Sources/GRPCHealthService/HealthService+Service.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ private import Synchronization
2222
extension HealthService {
2323
internal struct Service: Grpc_Health_V1_Health.ServiceProtocol {
2424
private let state = Self.State()
25+
/// Defines the maximum number of resources a `List` request can return.
26+
/// An `RPCError` with the code `ResourceExhaused` is thrown if this limit is exceeded.
27+
private let listMaxAllowedServices = 100
2528
}
2629
}
2730

@@ -49,6 +52,13 @@ extension HealthService.Service {
4952
) async throws -> ServerResponse<Grpc_Health_V1_HealthListResponse> {
5053
let serviceStatuses = self.state.listStatuses()
5154

55+
guard serviceStatuses.count <= listMaxAllowedServices else {
56+
throw RPCError(
57+
code: .resourceExhausted,
58+
message: "Server health list exceeds maximum capacity: \(listMaxAllowedServices)."
59+
)
60+
}
61+
5262
var listResponse = Grpc_Health_V1_HealthListResponse()
5363

5464
for (service, status) in serviceStatuses {

Tests/GRPCHealthServiceTests/HealthTests.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,36 @@ final class HealthTests: XCTestCase {
344344
XCTAssertEqual(try XCTUnwrap(response.statuses[""]?.status), .serving)
345345
}
346346
}
347+
348+
func testListExceedingMaxAllowedServices() async throws {
349+
try await withHealthClient { (healthClient, healthProvider) in
350+
let message = Grpc_Health_V1_HealthListRequest()
351+
let listMaxAllowedServices = 100
352+
353+
for index in 1 ... listMaxAllowedServices {
354+
healthProvider.updateStatus(
355+
.notServing,
356+
forService: ServiceDescriptor(package: "test", service: "Service\(index)")
357+
)
358+
359+
let response = try await healthClient.list(message)
360+
XCTAssertTrue(response.statuses.count == index)
361+
}
362+
363+
healthProvider.updateStatus(.notServing, forService: ServiceDescriptor.testService)
364+
365+
do {
366+
_ = try await healthClient.list(message)
367+
XCTFail("should error")
368+
} catch {
369+
let resolvedError = try XCTUnwrap(
370+
error as? RPCError,
371+
"health client list throws unexpected error: \(error)"
372+
)
373+
XCTAssertEqual(resolvedError.code, .resourceExhausted)
374+
}
375+
}
376+
}
347377
}
348378

349379
@available(gRPCSwiftExtras 2.0, *)

0 commit comments

Comments
 (0)