Skip to content

Commit

Permalink
simplify reconnection logic by always reconnecting from Monitor
Browse files Browse the repository at this point in the history
  • Loading branch information
lhoward committed Nov 27, 2024
1 parent 660dd34 commit 548b782
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 77 deletions.
69 changes: 3 additions & 66 deletions Sources/SwiftOCA/OCP.1/Ocp1Connection+Connect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,32 +253,8 @@ extension Ocp1Connection {
// MARK: - reconnection handling

extension Ocp1Connection {
enum ReconnectionPolicy {
/// do not try to automatically reconnect on connection failure
case noReconnect
/// try to reconnect in the keepAlive monitor task
case reconnectInMonitor
/// try to reconnect before sending the next message
case reconnectOnSend
}

///
/// Re-connection logic is as follows:
///
/// * If the connection has a heartbeat, then automatic reconnection is only
/// managed in the / heartbeat task
///
/// * If the connection does not have a heartbeat, than automatic
/// reconnection is managed when / sending a PDU
///
private var _reconnectionPolicy: ReconnectionPolicy {
if !options.flags.contains(.automaticReconnect) {
.noReconnect
} else if heartbeatTime == .zero {
.reconnectOnSend
} else {
.reconnectInMonitor
}
private var _automaticReconnect: Bool {
options.flags.contains(.automaticReconnect)
}

/// reconnect to the OCA device with exponential backoff, updating
Expand Down Expand Up @@ -322,49 +298,10 @@ extension Ocp1Connection {
}
}

private var _needsReconnectOnSend: Bool {
guard _reconnectionPolicy == .reconnectOnSend else { return false }

switch _connectionState.value {
case .notConnected:
fallthrough
case .connectionTimedOut:
fallthrough
case .connectionFailed:
return true
default:
return false
}
}

func willSendMessage() async throws {
guard _needsReconnectOnSend else { return }
try await reconnectDeviceWithBackoff()
}

func didSendMessage(error: Ocp1Error? = nil) async throws {
if error == nil {
lastMessageSentTime = Monitor.now
}

if _reconnectionPolicy != .reconnectInMonitor, let error,
let connectionState = error.connectionState
{
logger
.debug(
"failed to send message: error \(error), new connection state \(connectionState); disconnecting"
)
if isConnected {
updateConnectionState(connectionState)
try await _disconnectDeviceAfterConnectionFailure()
}
}
}

private func _onMonitorError(_ error: Error) async throws {
updateConnectionState(error.ocp1ConnectionState)

if error._isRecoverableConnectionError, _reconnectionPolicy == .reconnectInMonitor {
if error._isRecoverableConnectionError, _automaticReconnect {
logger.trace("expiring connection after receiving error \(error)")
try await _disconnectDeviceAfterConnectionFailure()
Task.detached { try await self.reconnectDeviceWithBackoff() }
Expand Down
13 changes: 2 additions & 11 deletions Sources/SwiftOCA/OCP.1/Ocp1Connection+Messages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,9 @@ extension Ocp1Connection {
) async throws {
let messagePduData = try Self.encodeOcp1MessagePdu(messages, type: messageType)

try await willSendMessage()

do {
guard try await write(messagePduData) == messagePduData.count else {
throw Ocp1Error.pduSendingFailed
}
} catch let error as Ocp1Error {
try await didSendMessage(error: error)
throw error
guard try await write(messagePduData) == messagePduData.count else {
throw Ocp1Error.pduSendingFailed
}

try await didSendMessage()
}

private func sendMessage(
Expand Down

0 comments on commit 548b782

Please sign in to comment.