Skip to content

Commit bb34d70

Browse files
committed
Remove /init/error and improve /invocation/error output
1 parent 5fadfbc commit bb34d70

File tree

10 files changed

+51
-250
lines changed

10 files changed

+51
-250
lines changed

Sources/TencentSCFRuntimeCore/SCF+LocalServer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private enum LocalFunction {
165165
}
166166

167167
// `/next` endpoint is called by the SCF instance polling for work.
168-
case (.GET, let url) where url == Consts.getNextInvocationURL:
168+
case (.GET, let url) where url == Endpoint.getNextInvocation:
169169
// Check if our server is in the correct state.
170170
guard case .waitingForSCFRequest = Self.invocationState else {
171171
self.logger.error("invalid invocation state \(Self.invocationState)")
@@ -197,7 +197,7 @@ private enum LocalFunction {
197197
}
198198

199199
// `/response` endpoint is called by the cloud function posting the response.
200-
case (.POST, let url) where url == Consts.postResponseURL:
200+
case (.POST, let url) where url == Endpoint.postResponse:
201201
guard case .waitingForSCFResponse(let invocation) = Self.invocationState else {
202202
// A response was sent, but we did not expect to receive one.
203203
self.logger.error("invalid invocation state \(Self.invocationState)")
@@ -209,7 +209,7 @@ private enum LocalFunction {
209209
Self.invocationState = .waitingForSCFRequest
210210

211211
// `/error` endpoint is called by the cloud function posting an error response.
212-
case (.POST, let url) where url == Consts.postErrorURL:
212+
case (.POST, let url) where url == Endpoint.postError:
213213
guard case .waitingForSCFResponse(let invocation) = Self.invocationState else {
214214
// A response was sent, but we did not expect to receive one.
215215
self.logger.error("invalid invocation state \(Self.invocationState)")

Sources/TencentSCFRuntimeCore/SCFRunner.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,10 @@ extension SCF {
6565
self.runtimeClient.reportInitializationReady(logger: logger)
6666
.mapResult { _ in handler }
6767
}
68-
.peekError { error in
69-
self.runtimeClient.reportInitializationError(logger: logger, error: error).peekError { reportingError in
70-
// We're going to bail out because the init failed, so there's not a lot we
71-
// can do other than log that we couldn't report this error back to the runtime.
72-
logger.error("failed reporting initialization error to scf runtime engine: \(reportingError)")
73-
}
68+
.peekError { error -> Void in
69+
// We're going to terminate because the init failed, so there's not a lot we
70+
// can do other than log the error back to the runtime.
71+
logger.error("initialization fail with error: \(error)")
7472
}
7573
}
7674

Sources/TencentSCFRuntimeCore/SCFRuntimeClient.swift

Lines changed: 9 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@ import NIO
3030
import NIOHTTP1
3131

3232
/// An HTTP based client for SCF Runtime Engine. This encapsulates the RESTful methods exposed by the runtime engine:
33-
/// * /runtime/invocation/next
34-
/// * /runtime/invocation/response
35-
/// * /runtime/invocation/error
36-
/// * /runtime/init/ready
37-
/// * /runtime/init/error
33+
/// - POST /runtime/init/ready
34+
/// - GET /runtime/invocation/next
35+
/// - POST /runtime/invocation/response
36+
/// - POST /runtime/invocation/error
3837
extension SCF {
3938
internal struct RuntimeClient {
4039
private let eventLoop: EventLoop
@@ -48,7 +47,7 @@ extension SCF {
4847

4948
/// Requests invocation from the API server.
5049
func getNextInvocation(logger: Logger) -> EventLoopFuture<(Invocation, ByteBuffer)> {
51-
let url = Consts.getNextInvocationURL
50+
let url = Endpoint.getNextInvocation
5251
logger.debug("requesting work from scf runtime engine using \(url)")
5352
return self.httpClient.get(url: url, headers: RuntimeClient.defaultHeaders).flatMapThrowing { response in
5453
guard response.status == .ok else {
@@ -79,15 +78,12 @@ extension SCF {
7978

8079
switch result {
8180
case .success(let buffer):
82-
url = Consts.postResponseURL
81+
url = Endpoint.postResponse
8382
body = buffer
8483
headers = RuntimeClient.defaultHeaders
8584
case .failure(let error):
86-
url = Consts.postErrorURL
87-
let errorResponse = ErrorResponse(errorType: Consts.functionError, errorMessage: "\(error)")
88-
let bytes = errorResponse.toJSONBytes()
89-
body = self.allocator.buffer(capacity: bytes.count)
90-
body!.writeBytes(bytes)
85+
url = Endpoint.postError
86+
body = self.allocator.buffer(string: "\(error)")
9187
headers = RuntimeClient.errorHeaders
9288
}
9389
logger.debug("reporting results to scf runtime engine using \(url)")
@@ -110,7 +106,7 @@ extension SCF {
110106

111107
/// Reports initialization ready to the runtime engine.
112108
func reportInitializationReady(logger: Logger) -> EventLoopFuture<Void> {
113-
let url = Consts.postInitReadyURL
109+
let url = Endpoint.postInitReady
114110
logger.info("reporting initialization ready to scf runtime engine using \(url)")
115111
return self.httpClient.post(url: url, headers: RuntimeClient.defaultHeaders, body: .init(string: " ")).flatMapThrowing { response in
116112
guard response.status == .ok else {
@@ -129,31 +125,6 @@ extension SCF {
129125
}
130126
}
131127

132-
/// Reports an initialization error to the runtime engine.
133-
func reportInitializationError(logger: Logger, error: Error) -> EventLoopFuture<Void> {
134-
let url = Consts.postInitErrorURL
135-
let errorResponse = ErrorResponse(errorType: Consts.initializationError, errorMessage: "\(error)")
136-
let bytes = errorResponse.toJSONBytes()
137-
var body = self.allocator.buffer(capacity: bytes.count)
138-
body.writeBytes(bytes)
139-
logger.warning("reporting initialization error to scf runtime engine using \(url)")
140-
return self.httpClient.post(url: url, headers: RuntimeClient.errorHeaders, body: body).flatMapThrowing { response in
141-
guard response.status == .ok else {
142-
throw RuntimeError.badStatusCode(response.status)
143-
}
144-
return ()
145-
}.flatMapErrorThrowing { error in
146-
switch error {
147-
case HTTPClient.Errors.timeout:
148-
throw RuntimeError.upstreamError("timeout")
149-
case HTTPClient.Errors.connectionResetByPeer:
150-
throw RuntimeError.upstreamError("connectionResetByPeer")
151-
default:
152-
throw error
153-
}
154-
}
155-
}
156-
157128
/// Cancels the current request if one is already running. Only needed for debugging purposes.
158129
func cancel() {
159130
self.httpClient.cancel()
@@ -172,24 +143,6 @@ internal extension SCF {
172143
}
173144
}
174145

175-
internal struct ErrorResponse: Codable {
176-
var errorType: String
177-
var errorMessage: String
178-
}
179-
180-
internal extension ErrorResponse {
181-
func toJSONBytes() -> [UInt8] {
182-
var bytes = [UInt8]()
183-
bytes.append(UInt8(ascii: "{"))
184-
bytes.append(contentsOf: #""errorType":"# .utf8)
185-
self.errorType.encodeAsJSONString(into: &bytes)
186-
bytes.append(contentsOf: #","errorMessage":"# .utf8)
187-
self.errorMessage.encodeAsJSONString(into: &bytes)
188-
bytes.append(UInt8(ascii: "}"))
189-
return bytes
190-
}
191-
}
192-
193146
extension SCF {
194147
internal struct Invocation {
195148
let requestID: String

Sources/TencentSCFRuntimeCore/Utils.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,11 @@
2828
import Dispatch
2929
import NIO
3030

31-
internal enum Consts {
32-
static let getNextInvocationURL = "/runtime/invocation/next"
33-
static let postResponseURL = "/runtime/invocation/response"
34-
static let postErrorURL = "/runtime/invocation/error"
35-
static let postInitErrorURL = "/runtime/init/error"
36-
static let postInitReadyURL = "/runtime/init/ready"
37-
static let functionError = "FunctionError"
38-
static let initializationError = "InitializationError"
31+
internal enum Endpoint {
32+
static let getNextInvocation = "/runtime/invocation/next"
33+
static let postResponse = "/runtime/invocation/response"
34+
static let postError = "/runtime/invocation/error"
35+
static let postInitReady = "/runtime/init/ready"
3936
}
4037

4138
/// Tencent SCF HTTP Headers, used to populate the `SCF.Context` object.

Tests/TencentSCFRuntimeCoreTests/MockSCFServer.swift

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,7 @@ internal final class HTTPHandler: ChannelInboundHandler {
132132
var responseBody: String?
133133
var responseHeaders: [(String, String)]?
134134

135-
// Handle post-init-error first to avoid matching the less specific post-error suffix.
136-
if request.head.uri == Consts.postInitErrorURL {
137-
guard let json = requestBody, let error = ErrorResponse.fromJson(json) else {
138-
return self.writeResponse(context: context, status: .badRequest)
139-
}
140-
switch self.behavior.process(initError: error) {
141-
case .success:
142-
responseStatus = .ok
143-
case .failure(let error):
144-
responseStatus = .init(statusCode: error.rawValue)
145-
}
146-
} else if request.head.uri == Consts.getNextInvocationURL {
135+
if request.head.uri == Endpoint.getNextInvocation {
147136
switch self.behavior.getInvocation() {
148137
case .success(let (requestId, result)):
149138
if requestId == "timeout" {
@@ -161,17 +150,15 @@ internal final class HTTPHandler: ChannelInboundHandler {
161150
case .failure(let error):
162151
responseStatus = .init(statusCode: error.rawValue)
163152
}
164-
} else if request.head.uri == Consts.postResponseURL {
153+
} else if request.head.uri == Endpoint.postResponse {
165154
switch self.behavior.process(response: requestBody) {
166155
case .success:
167156
responseStatus = .ok
168157
case .failure(let error):
169158
responseStatus = .init(statusCode: error.rawValue)
170159
}
171-
} else if request.head.uri == Consts.postErrorURL {
172-
guard let json = requestBody,
173-
let error = ErrorResponse.fromJson(json)
174-
else {
160+
} else if request.head.uri == Endpoint.postError {
161+
guard let error = requestBody else {
175162
return self.writeResponse(context: context, status: .badRequest)
176163
}
177164
switch self.behavior.process(error: error) {
@@ -222,8 +209,7 @@ internal final class HTTPHandler: ChannelInboundHandler {
222209
internal protocol SCFServerBehavior {
223210
func getInvocation() -> GetInvocationResult
224211
func process(response: String?) -> Result<Void, ProcessResponseError>
225-
func process(error: ErrorResponse) -> Result<Void, ProcessErrorError>
226-
func process(initError: ErrorResponse) -> Result<Void, ProcessErrorError>
212+
func process(error: String) -> Result<Void, ProcessErrorError>
227213
}
228214

229215
internal typealias GetInvocationResult = Result<(String, String), GetWorkError>
@@ -251,18 +237,3 @@ internal enum ServerError: Error {
251237
case notReady
252238
case cantBind
253239
}
254-
255-
private extension ErrorResponse {
256-
static func fromJson(_ s: String) -> ErrorResponse? {
257-
let decoder = JSONDecoder()
258-
do {
259-
if let data = s.data(using: .utf8) {
260-
return try decoder.decode(ErrorResponse.self, from: data)
261-
} else {
262-
return nil
263-
}
264-
} catch {
265-
return nil
266-
}
267-
}
268-
}

Tests/TencentSCFRuntimeCoreTests/SCF+StringTest.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,20 +239,15 @@ private struct Behavior: SCFServerBehavior {
239239
}
240240
}
241241

242-
func process(error: ErrorResponse) -> Result<Void, ProcessErrorError> {
242+
func process(error: String) -> Result<Void, ProcessErrorError> {
243243
XCTAssertEqual(self.requestId, self.requestId, "expecting requestId to match")
244244
switch self.result {
245245
case .success:
246246
XCTFail("unexpected to succeed, but failed with: \(error)")
247247
return .failure(.internalServerError)
248248
case .failure(let expected):
249-
XCTAssertEqual(expected.description, error.errorMessage, "expecting error to match")
249+
XCTAssertEqual(expected.description, error, "expecting error to match")
250250
return .success(())
251251
}
252252
}
253-
254-
func process(initError: ErrorResponse) -> Result<Void, ProcessErrorError> {
255-
XCTFail("should not report init error")
256-
return .failure(.internalServerError)
257-
}
258253
}

Tests/TencentSCFRuntimeCoreTests/SCFLifecycleTest.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,7 @@ struct BadBehavior: SCFServerBehavior {
143143
return .failure(.internalServerError)
144144
}
145145

146-
func process(error: ErrorResponse) -> Result<Void, ProcessErrorError> {
147-
XCTFail("should not report an error")
148-
return .failure(.internalServerError)
149-
}
150-
151-
func process(initError: ErrorResponse) -> Result<Void, ProcessErrorError> {
146+
func process(error: String) -> Result<Void, ProcessErrorError> {
152147
XCTFail("should not report an error")
153148
return .failure(.internalServerError)
154149
}

Tests/TencentSCFRuntimeCoreTests/SCFRunnerTest.swift

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,10 @@ class SCFRunnerTest: XCTestCase {
4242
return .success(())
4343
}
4444

45-
func process(error: ErrorResponse) -> Result<Void, ProcessErrorError> {
45+
func process(error: String) -> Result<Void, ProcessErrorError> {
4646
XCTFail("should not report error")
4747
return .failure(.internalServerError)
4848
}
49-
50-
func process(initError: ErrorResponse) -> Result<Void, ProcessErrorError> {
51-
XCTFail("should not report init error")
52-
return .failure(.internalServerError)
53-
}
5449
}
5550
XCTAssertNoThrow(try runSCF(behavior: Behavior(), handler: EchoHandler()))
5651
}
@@ -68,15 +63,10 @@ class SCFRunnerTest: XCTestCase {
6863
return .failure(.internalServerError)
6964
}
7065

71-
func process(error: ErrorResponse) -> Result<Void, ProcessErrorError> {
72-
XCTAssertEqual(Behavior.error, error.errorMessage, "expecting error to match")
66+
func process(error: String) -> Result<Void, ProcessErrorError> {
67+
XCTAssertEqual(Behavior.error, error, "expecting error to match")
7368
return .success(())
7469
}
75-
76-
func process(initError: ErrorResponse) -> Result<Void, ProcessErrorError> {
77-
XCTFail("should not report init error")
78-
return .failure(.internalServerError)
79-
}
8070
}
8171
XCTAssertNoThrow(try runSCF(behavior: Behavior(), handler: FailedHandler(Behavior.error)))
8272
}

0 commit comments

Comments
 (0)