Skip to content

Commit

Permalink
Merge pull request #11 from amzn/invocation_strategy
Browse files Browse the repository at this point in the history
Add an invocation strategy protocol to specify how to invoke the HTTP1RequestHandler
  • Loading branch information
tachyonics committed Oct 31, 2018
2 parents 39614ca + 63cdde0 commit 57ed50c
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 8 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Expand Up @@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
"revision": "5d8148c8b45dfb449276557f22120694567dd1d2",
"version": "1.9.5"
"revision": "176dd6e8564d60e936b76f3a896d667ae3acba31",
"version": "1.10.0"
}
},
{
Expand Down
36 changes: 36 additions & 0 deletions Sources/SmokeHTTP1/GlobalDispatchQueueInvocationStrategy.swift
@@ -0,0 +1,36 @@
// Copyright 2018 Amazon.com, Inc. or its affiliates. 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.
// A copy of the License is located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file 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.
//
// GlobalDispatchQueueAsyncInvocationStrategy.swift
// SmokeHTTP1
//

import Foundation

/**
An AsyncInvocationStrategy that will invocate the handler on
DispatchQueue.global().
*/
public struct GlobalDispatchQueueInvocationStrategy: InvocationStrategy {
let queue = DispatchQueue.global()

public init() {

}

public func invoke(handler: @escaping () -> ()) {
queue.async {
handler()
}
}
}
13 changes: 11 additions & 2 deletions Sources/SmokeHTTP1/HTTP1ChannelInboundHandler.swift
Expand Up @@ -53,14 +53,17 @@ class HTTP1ChannelInboundHandler: ChannelInboundHandler {
}

private let handler: HTTP1RequestHandler
private let invocationStrategy: InvocationStrategy
private var requestHead: HTTPRequestHead?

var bodyParts: [ByteBuffer] = []
private var keepAliveStatus = KeepAliveStatus()
private var state = State.idle

init(handler: HTTP1RequestHandler) {
init(handler: HTTP1RequestHandler,
invocationStrategy: InvocationStrategy) {
self.handler = handler
self.invocationStrategy = invocationStrategy
}

private func reset() {
Expand Down Expand Up @@ -132,8 +135,14 @@ class HTTP1ChannelInboundHandler: ChannelInboundHandler {
context: ctx,
wrapOutboundOut: wrapOutboundOut)

let currentHandler = handler

// pass to the request handler to complete
handler.handle(requestHead: requestHead, body: requestBodyData, responseHandler: responseHandler)
invocationStrategy.invoke {
currentHandler.handle(requestHead: requestHead,
body: requestBodyData,
responseHandler: responseHandler)
}
}

/**
Expand Down
32 changes: 32 additions & 0 deletions Sources/SmokeHTTP1/InvocationStrategy.swift
@@ -0,0 +1,32 @@
// Copyright 2018 Amazon.com, Inc. or its affiliates. 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.
// A copy of the License is located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file 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.
//
// AsyncInvocationStrategy.swift
// SmokeHTTP1
//

import Foundation

/**
A strategy protocol that manages how to invocate a handler.
*/
public protocol InvocationStrategy {

/**
Function to handle the invocation of the handler.
- Parameters:
- handler: The handler to invocate.
*/
func invoke(handler: @escaping () -> ())
}
10 changes: 8 additions & 2 deletions Sources/SmokeHTTP1/SmokeHTTP1Server.swift
Expand Up @@ -36,6 +36,7 @@ public class SmokeHTTP1Server {
let group: MultiThreadedEventLoopGroup
let threadPool: BlockingIOThreadPool
let handler: HTTP1RequestHandler
let invocationStrategy: InvocationStrategy
var channel: Channel?

/**
Expand All @@ -49,10 +50,12 @@ public class SmokeHTTP1Server {
*/
public init(handler: HTTP1RequestHandler,
port: Int = ServerDefaults.defaultPort,
serverThreads: Int = ServerDefaults.defaultServerThreads) {
serverThreads: Int = ServerDefaults.defaultServerThreads,
invocationStrategy: InvocationStrategy = GlobalDispatchQueueInvocationStrategy()) {
self.port = port
self.serverThreads = serverThreads
self.handler = handler
self.invocationStrategy = invocationStrategy

self.group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
self.threadPool = BlockingIOThreadPool(numberOfThreads: serverThreads)
Expand All @@ -66,6 +69,7 @@ public class SmokeHTTP1Server {
threadPool.start()

let currentHandler = handler
let currentInvocationStrategy = invocationStrategy

// create a ServerBootstrap with a HTTP Server pipeline that delegates
// to a HTTPChannelInboundHandler
Expand All @@ -74,7 +78,9 @@ public class SmokeHTTP1Server {
.serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
.childChannelInitializer { channel in
channel.pipeline.configureHTTPServerPipeline().then {
channel.pipeline.add(handler: HTTP1ChannelInboundHandler(handler: currentHandler))
channel.pipeline.add(handler: HTTP1ChannelInboundHandler(
handler: currentHandler,
invocationStrategy: currentInvocationStrategy))
}
}
.childChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
Expand Down
Expand Up @@ -34,15 +34,17 @@ public extension SmokeHTTP1Server {
withHandlerSelector handlerSelector: SelectorType,
andContext context: ContextType,
defaultOperationDelegate: OperationDelegateType,
andPort port: Int = ServerDefaults.defaultPort) throws
andPort port: Int = ServerDefaults.defaultPort,
invocationStrategy: InvocationStrategy = GlobalDispatchQueueInvocationStrategy()) throws
where SelectorType: SmokeHTTP1HandlerSelector, SelectorType.ContextType == ContextType,
SelectorType.OperationDelegateType == OperationDelegateType, OperationDelegateType.RequestType == SmokeHTTP1Request,
OperationDelegateType.ResponseHandlerType == HTTP1ResponseHandler {
let handler = OperationServerHTTP1RequestHandler(handlerSelector: handlerSelector,
context: context,
defaultOperationDelegate: defaultOperationDelegate)
let server = SmokeHTTP1Server(handler: handler,
port: port)
port: port,
invocationStrategy: invocationStrategy)

Log.info("Server starting on port \(port)...")

Expand Down

0 comments on commit 57ed50c

Please sign in to comment.