From 31a03ceca2f6755a83378c8cb0a0745abe7236ec Mon Sep 17 00:00:00 2001 From: George Barnett Date: Thu, 11 Jun 2020 11:13:14 +0100 Subject: [PATCH] Turn the RequestIDProvider enum into a struct (#839) Motivation: Public enums are bad for API evolution. There's no reason the RequestIDProvider can't be a struct instead. Modifications: - Turn RequestIDProvider into a struct Result: - Lower risk of API breakage --- Sources/GRPC/ClientOptions.swift | 41 +++++++++++++------- Tests/GRPCTests/RequestIDProviderTests.swift | 37 ++++++++++++++++++ Tests/GRPCTests/XCTestManifests.swift | 12 ++++++ 3 files changed, 77 insertions(+), 13 deletions(-) create mode 100644 Tests/GRPCTests/RequestIDProviderTests.swift diff --git a/Sources/GRPC/ClientOptions.swift b/Sources/GRPC/ClientOptions.swift index 01ed2e71d..c92d5f1a1 100644 --- a/Sources/GRPC/ClientOptions.swift +++ b/Sources/GRPC/ClientOptions.swift @@ -74,25 +74,40 @@ public struct CallOptions { self.cacheable = false } - /// How Request IDs should be provided. - public enum RequestIDProvider { - /// Generate a new ID automatically. - case autogenerated + public struct RequestIDProvider { + private enum RequestIDSource { + case `static`(String) + case generated(() -> String) + } + + private var source: RequestIDSource + private init(_ source: RequestIDSource) { + self.source = source + } + + internal func requestID() -> String { + switch self.source { + case .static(let requestID): + return requestID + case .generated(let generator): + return generator() + } + } + + /// Generate a new request ID for each RPC. + public static let autogenerated = RequestIDProvider(.generated({ UUID().uuidString })) /// Specify an ID to be used. /// /// - Important: this should only be used when `CallOptions` are passed directly to the call. /// If it is used for the default options on a client then all calls with have the same ID. - case userDefined(String) - - func requestID() -> String { - switch self { - case .autogenerated: - return UUID().uuidString + public static func userDefined(_ requestID: String) -> RequestIDProvider { + return RequestIDProvider(.static(requestID)) + } - case .userDefined(let id): - return id - } + /// Provide a factory to generate request IDs. + public static func generated(_ requestIDFactory: @escaping () -> String) -> RequestIDProvider { + return RequestIDProvider(.generated(requestIDFactory)) } } } diff --git a/Tests/GRPCTests/RequestIDProviderTests.swift b/Tests/GRPCTests/RequestIDProviderTests.swift new file mode 100644 index 000000000..7fad61f35 --- /dev/null +++ b/Tests/GRPCTests/RequestIDProviderTests.swift @@ -0,0 +1,37 @@ +/* + * Copyright 2020, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@testable import GRPC +import XCTest + +class RequestIDProviderTests: GRPCTestCase { + func testUserDefined() { + let provider = CallOptions.RequestIDProvider.userDefined("foo") + XCTAssertEqual(provider.requestID(), "foo") + XCTAssertEqual(provider.requestID(), "foo") + } + + func testAutogenerated() { + let provider = CallOptions.RequestIDProvider.autogenerated + XCTAssertNotEqual(provider.requestID(), provider.requestID()) + } + + func testGenerator() { + let provider = CallOptions.RequestIDProvider.generated { + return "foo" + } + XCTAssertEqual(provider.requestID(), "foo") + } +} diff --git a/Tests/GRPCTests/XCTestManifests.swift b/Tests/GRPCTests/XCTestManifests.swift index 6a27f9d0f..5c01ccaf2 100644 --- a/Tests/GRPCTests/XCTestManifests.swift +++ b/Tests/GRPCTests/XCTestManifests.swift @@ -614,6 +614,17 @@ extension ReadStateTests { ] } +extension RequestIDProviderTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__RequestIDProviderTests = [ + ("testAutogenerated", testAutogenerated), + ("testGenerator", testGenerator), + ("testUserDefined", testUserDefined), + ] +} + extension ServerDelayedThrowingTests { // DO NOT MODIFY: This is autogenerated, use: // `swift test --generate-linuxmain` @@ -746,6 +757,7 @@ public func __allTests() -> [XCTestCaseEntry] { testCase(MessageEncodingHeaderValidatorTests.__allTests__MessageEncodingHeaderValidatorTests), testCase(PlatformSupportTests.__allTests__PlatformSupportTests), testCase(ReadStateTests.__allTests__ReadStateTests), + testCase(RequestIDProviderTests.__allTests__RequestIDProviderTests), testCase(ServerDelayedThrowingTests.__allTests__ServerDelayedThrowingTests), testCase(ServerErrorTransformingTests.__allTests__ServerErrorTransformingTests), testCase(ServerTLSErrorTests.__allTests__ServerTLSErrorTests),