Skip to content

Commit

Permalink
Add ConnectionIDGenerator and NoOpKeepAliveBehavior (#418)
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianfett authored Oct 16, 2023
1 parent 8fbf8ff commit 358fa59
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 1 deletion.
15 changes: 15 additions & 0 deletions Sources/ConnectionPoolModule/ConnectionIDGenerator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Atomics

public struct ConnectionIDGenerator: ConnectionIDGeneratorProtocol {
static let globalGenerator = ConnectionIDGenerator()

private let atomic: ManagedAtomic<Int>

public init() {
self.atomic = .init(0)
}

public func next() -> Int {
return self.atomic.loadThenWrappingIncrement(ordering: .relaxed)
}
}
8 changes: 8 additions & 0 deletions Sources/ConnectionPoolModule/NoKeepAliveBehavior.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
public struct NoOpKeepAliveBehavior<Connection: PooledConnection>: ConnectionKeepAliveBehavior {
public var keepAliveFrequency: Duration? { nil }

public func runKeepAlive(for connection: Connection) async throws {}

public init(connectionType: Connection.Type) {}
}
22 changes: 22 additions & 0 deletions Tests/ConnectionPoolModuleTests/ConnectionIDGeneratorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import _ConnectionPoolModule
import XCTest

final class ConnectionIDGeneratorTests: XCTestCase {
func testGenerateConnectionIDs() async {
let idGenerator = ConnectionIDGenerator()

XCTAssertEqual(idGenerator.next(), 0)
XCTAssertEqual(idGenerator.next(), 1)
XCTAssertEqual(idGenerator.next(), 2)

await withTaskGroup(of: Void.self) { taskGroup in
for _ in 0..<1000 {
taskGroup.addTask {
_ = idGenerator.next()
}
}
}

XCTAssertEqual(idGenerator.next(), 1003)
}
}
74 changes: 74 additions & 0 deletions Tests/ConnectionPoolModuleTests/Mocks/MockConnection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import DequeModule
@testable import _ConnectionPoolModule

// Sendability enforced through the lock
final class MockConnection: PooledConnection, @unchecked Sendable {
typealias ID = Int

let id: ID

private enum State {
case running([@Sendable ((any Error)?) -> ()])
case closing([@Sendable ((any Error)?) -> ()])
case closed
}

private let lock = NIOLock()
private var _state = State.running([])

init(id: Int) {
self.id = id
}

func onClose(_ closure: @escaping @Sendable ((any Error)?) -> ()) {
let enqueued = self.lock.withLock { () -> Bool in
switch self._state {
case .closed:
return false

case .running(var callbacks):
callbacks.append(closure)
self._state = .running(callbacks)
return true

case .closing(var callbacks):
callbacks.append(closure)
self._state = .closing(callbacks)
return true
}
}

if !enqueued {
closure(nil)
}
}

func close() {
self.lock.withLock {
switch self._state {
case .running(let callbacks):
self._state = .closing(callbacks)

case .closing, .closed:
break
}
}
}

func closeIfClosing() {
let callbacks = self.lock.withLock { () -> [@Sendable ((any Error)?) -> ()] in
switch self._state {
case .running, .closed:
return []

case .closing(let callbacks):
self._state = .closed
return callbacks
}
}

for callback in callbacks {
callback(nil)
}
}
}
10 changes: 10 additions & 0 deletions Tests/ConnectionPoolModuleTests/NoKeepAliveBehaviorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import _ConnectionPoolModule
import XCTest

@available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
final class NoKeepAliveBehaviorTests: XCTestCase {
func testNoKeepAlive() {
let keepAliveBehavior = NoOpKeepAliveBehavior(connectionType: MockConnection.self)
XCTAssertNil(keepAliveBehavior.keepAliveFrequency)
}
}
1 change: 0 additions & 1 deletion Tests/ConnectionPoolModuleTests/gitkeep.swift

This file was deleted.

0 comments on commit 358fa59

Please sign in to comment.