Skip to content

Commit

Permalink
Use serial dispatch queue for connect (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
alfianlosari authored Jan 31, 2023
1 parent f815729 commit dc556e9
Show file tree
Hide file tree
Showing 12 changed files with 56 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .github/scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ set -eo pipefail

xcodebuild -workspace Courier.xcworkspace \
-scheme CourierTests \
-destination platform=iOS\ Simulator,OS=16.0,name=iPhone\ 13 \
-destination platform=iOS\ Simulator,OS=16.2,name=iPhone\ 13 \
clean test | xcpretty
3 changes: 1 addition & 2 deletions CourierMQTT/MQTT/Client/MQTTClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ class MQTTClient: IMQTTClient {
authFailureHandler: configuration.authFailureHandler,
connectTimeoutPolicy: configuration.connectTimeoutPolicy,
idleActivityTimeoutPolicy: configuration.idleActivityTimeoutPolicy,
isPersistent: configuration.isMQTTPersistentEnabled,
shouldInitializeCoreDataPersistenceContext: configuration.shouldInitializeCoreDataPersistenceContext
isPersistent: configuration.isMQTTPersistentEnabled
)

connection = mqttConnectionFactory.makeConnection(connectionConfig: connectionConfig)
Expand Down
1 change: 0 additions & 1 deletion CourierMQTT/MQTT/Configuration/IMQTTConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ protocol IMQTTConfiguration {
var messageCleanupInterval: TimeInterval { get }

var isMQTTPersistentEnabled: Bool { get }
var shouldInitializeCoreDataPersistenceContext: Bool { get }
}
5 changes: 1 addition & 4 deletions CourierMQTT/MQTT/Configuration/MQTTConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ struct MQTTConfiguration: IMQTTConfiguration {
var messagePersistenceTTLSeconds: TimeInterval
var messageCleanupInterval: TimeInterval
var isMQTTPersistentEnabled: Bool
var shouldInitializeCoreDataPersistenceContext: Bool

init(connectRetryTimePolicy: IConnectRetryTimePolicy = ConnectRetryTimePolicy(),
connectTimeoutPolicy: IConnectTimeoutPolicy = ConnectTimeoutPolicy(),
Expand All @@ -19,8 +18,7 @@ struct MQTTConfiguration: IMQTTConfiguration {
eventHandler: ICourierEventHandler,
messagePersistenceTTLSeconds: TimeInterval = 0,
messageCleanupInterval: TimeInterval = 10,
isMQTTPersistentEnabled: Bool,
shouldInitializeCoreDataPersistenceContext: Bool) {
isMQTTPersistentEnabled: Bool) {
self.connectRetryTimePolicy = connectRetryTimePolicy
self.connectTimeoutPolicy = connectTimeoutPolicy
self.idleActivityTimeoutPolicy = idleActivityTimeoutPolicy
Expand All @@ -29,6 +27,5 @@ struct MQTTConfiguration: IMQTTConfiguration {
self.messagePersistenceTTLSeconds = messagePersistenceTTLSeconds
self.messageCleanupInterval = messageCleanupInterval
self.isMQTTPersistentEnabled = isMQTTPersistentEnabled
self.shouldInitializeCoreDataPersistenceContext = shouldInitializeCoreDataPersistenceContext
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ struct MQTTClientFrameworkConnectionFactory: IMQTTConnectionFactory {
MQTTClientFrameworkConnection(connectionConfig: connectionConfig,
clientFactory: clientFactory,
persistenceFactory: MQTTPersistenceFactory(
isPersistent: connectionConfig.isPersistent,
shouldInitializeCoreDataPersistenceContext: connectionConfig.shouldInitializeCoreDataPersistenceContext))
isPersistent: connectionConfig.isPersistent))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ protocol IMQTTPersistenceFactory {
struct MQTTPersistenceFactory: IMQTTPersistenceFactory {

let isPersistent: Bool
let shouldInitializeCoreDataPersistenceContext: Bool

private let maxWindowSize: Int = 16
private let maxMessages: Int = 5000
private let maxSize: Int = 128 * 1024 * 1024

init(isPersistent: Bool = false, shouldInitializeCoreDataPersistenceContext: Bool = true) {
init(isPersistent: Bool = false) {
self.isPersistent = isPersistent
self.shouldInitializeCoreDataPersistenceContext = shouldInitializeCoreDataPersistenceContext
}

func makePersistence() -> MQTTPersistence {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,6 @@ class MQTTClientFrameworkSessionManager: NSObject, IMQTTClientFrameworkSessionMa
self.eventHandler = eventHandler

super.init()
if let coreDataPersistence = persistence as? MQTTCoreDataPersistence,
let persistenceFactory = mqttPersistenceFactory as? MQTTPersistenceFactory,
persistenceFactory.shouldInitializeCoreDataPersistenceContext {
queue.async { coreDataPersistence.initializeManagedObjectContext() }
}

self.updateState(to: .starting)
self.reconnectTimer = ReconnectTimer(retryInterval: retryInterval, maxRetryInterval: maxRetryInterval, queue: queue, reconnect: { [weak self] in
self?.reconnect()
Expand Down
29 changes: 16 additions & 13 deletions CourierMQTT/MQTT/MQTTCourierClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ class MQTTCourierClient: CourierClient {
eventHandler: courierEventHandler,
messagePersistenceTTLSeconds: config.messagePersistenceTTLSeconds,
messageCleanupInterval: config.messageCleanupInterval,
isMQTTPersistentEnabled: config.isMessagePersistenceEnabled,
shouldInitializeCoreDataPersistenceContext: config.shouldInitializeCoreDataPersistenceContext)
isMQTTPersistentEnabled: config.isMessagePersistenceEnabled)

let reachability = try? Reachability()
self.client = mqttClientFactory.makeClient(configuration: configuration, reachability: reachability, dispatchQueue: dispatchQueue)
Expand Down Expand Up @@ -108,21 +107,25 @@ class MQTTCourierClient: CourierClient {
authenticationTimeoutTimer?.schedule()

self.connectionServiceProvider.getConnectOptions { [weak self] result in
guard let self = self else { return }
isGettingConnectOptionsCompleted = true
self.authenticationTimeoutTimer?.stop()
self.authenticationTimeoutTimer = nil
self.isAuthenticating = false
if self.isDestroyed {
self.courierEventHandler.onEvent(.init(connectionInfo: self.client.connectOptions, event: .connectDiscarded(reason: "Courier client is destroyed")))
return
self?.dispatchQueue.async {
guard let self = self else { return }
isGettingConnectOptionsCompleted = true
self.authenticationTimeoutTimer?.stop()
self.authenticationTimeoutTimer = nil
self.isAuthenticating = false
if self.isDestroyed {
self.courierEventHandler.onEvent(.init(connectionInfo: self.client.connectOptions, event: .connectDiscarded(reason: "Courier client is destroyed")))
return
}
self.handleAuthenticationResult(result)
}
self.handleAuthenticationResult(result)
}
} else {
connectionServiceProvider.getConnectOptions { [weak self] result in
self?.isAuthenticating = false
self?.handleAuthenticationResult(result)
self?.dispatchQueue.async {
self?.isAuthenticating = false
self?.handleAuthenticationResult(result)
}
}
}
}
Expand Down
1 change: 0 additions & 1 deletion CourierMQTT/MQTT/Models/ConnectionConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ struct ConnectionConfig {
var idleActivityTimeoutPolicy: IdleActivityTimeoutPolicyProtocol

var isPersistent: Bool
var shouldInitializeCoreDataPersistenceContext: Bool
}
2 changes: 1 addition & 1 deletion CourierTests/Core/MQTT/Client/MQTTClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ extension MQTTClientTests {

var stubbedConfiguration: IMQTTConfiguration {
MQTTConfiguration(
connectRetryTimePolicy: mockConnectRetryTimePolicy, authFailureHandler: mockAuthFailureHandler, eventHandler: mockEventHandler, isMQTTPersistentEnabled: true, shouldInitializeCoreDataPersistenceContext: true)
connectRetryTimePolicy: mockConnectRetryTimePolicy, authFailureHandler: mockAuthFailureHandler, eventHandler: mockEventHandler, isMQTTPersistentEnabled: true)
}

var stubConnectOptions: ConnectOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ class MQTTClientFrameworkConnectionTests: XCTestCase {
authFailureHandler: mockAuthFailureHandler,
connectTimeoutPolicy: mockConnectTimeoutPolicy,
idleActivityTimeoutPolicy: IdleActivityTimeoutPolicy(),
isPersistent: true,
shouldInitializeCoreDataPersistenceContext: true
isPersistent: true
),
clientFactory: mockClientFactory,
persistenceFactory: mockPersistenceFactory
Expand Down
49 changes: 33 additions & 16 deletions CourierTests/Core/MQTT/MQTTCourierClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,44 @@ class MQTTCourierClientTests: XCTestCase {
func testConnectWithSuccessCredentials() {
mockConnectionServiceProvider.stubbedGetConnectOptionsCompletionResult = (.success(stubConnectOptions), ())
sut.connect()
if case .connectionServiceAuthSuccess = self.mockEventHandler.invokedOnEventParameters?.event.type {
} else {
XCTAssert(false)
let expectation_ = expectation(description: "test")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
expectation_.fulfill()
}
waitForExpectations(timeout: 0.1) { _ in
if case .connectionServiceAuthSuccess = self.mockEventHandler.invokedOnEventParameters?.event.type {
} else {
XCTAssert(false)
}
XCTAssertTrue(self.mockAuthRetryPolicy.invokedResetParams)
XCTAssertTrue(self.mockClient.invokedReset)
XCTAssertTrue(self.mockClient.invokedConnect)

XCTAssertEqual(self.mockClient.invokedConnectParameters?.connectOptions.host, self.stubConnectOptions.host)

XCTAssertEqual(self.mockClient.invokedConnectParameters?.connectOptions.port, UInt16(self.stubConnectOptions.port))
XCTAssertEqual(self.mockClient.invokedConnectParameters?.connectOptions.keepAlive, UInt16(self.pingInterval))
XCTAssertEqual(self.mockClient.invokedConnectParameters?.connectOptions.clientId, self.stubConnectOptions.clientId)
XCTAssertEqual(self.mockClient.invokedConnectParameters?.connectOptions.username, self.stubConnectOptions.username)
XCTAssertEqual(self.mockClient.invokedConnectParameters?.connectOptions.password, self.stubConnectOptions.password)

}
XCTAssertTrue(mockAuthRetryPolicy.invokedResetParams)
XCTAssertTrue(mockClient.invokedReset)
XCTAssertTrue(mockClient.invokedConnect)

XCTAssertEqual(mockClient.invokedConnectParameters?.connectOptions.host, stubConnectOptions.host)

XCTAssertEqual(mockClient.invokedConnectParameters?.connectOptions.port, UInt16(stubConnectOptions.port))
XCTAssertEqual(mockClient.invokedConnectParameters?.connectOptions.keepAlive, UInt16(pingInterval))
XCTAssertEqual(mockClient.invokedConnectParameters?.connectOptions.clientId, stubConnectOptions.clientId)
XCTAssertEqual(mockClient.invokedConnectParameters?.connectOptions.username, stubConnectOptions.username)
XCTAssertEqual(mockClient.invokedConnectParameters?.connectOptions.password, stubConnectOptions.password)
}




func testConnectWithFailureCredentials() {
mockConnectionServiceProvider.stubbedGetConnectOptionsCompletionResult = (.failure(stubbedError), ())
mockAuthRetryPolicy.stubbedGetRetryTimeResult = 0.1

sut.connect()
if case .connectionServiceAuthFailure = self.mockEventHandler.invokedOnEventParametersList[1]?.event.type {
let expectation_ = expectation(description: "test")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
expectation_.fulfill()
}
waitForExpectations(timeout: 0.1) { _ in
if case .connectionServiceAuthFailure = self.mockEventHandler.invokedOnEventParametersList[1]?.event.type {
XCTAssert(true)
} else {
XCTAssert(false)
Expand All @@ -127,7 +142,9 @@ class MQTTCourierClientTests: XCTestCase {
} else {
XCTAssert(false)
}
XCTAssertTrue(mockAuthRetryPolicy.invokedShouldRetry)
XCTAssertTrue(self.mockAuthRetryPolicy.invokedShouldRetry)
}

}

func testSubscribeTopics() {
Expand Down

0 comments on commit dc556e9

Please sign in to comment.