-
Notifications
You must be signed in to change notification settings - Fork 361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolves #170 - Return error on monitor disconnection #175
Resolves #170 - Return error on monitor disconnection #175
Conversation
Source/BluetoothManager.swift
Outdated
@@ -255,8 +255,8 @@ public class BluetoothManager { | |||
/// - parameter peripheral: The `Peripheral` to which the `BluetoothManager` is either trying to | |||
/// connect or has already connected. | |||
/// - returns: `Single` which emits next event when peripheral successfully cancelled connection. | |||
public func cancelPeripheralConnection(_ peripheral: Peripheral) -> Single<Peripheral> { | |||
let observable = Observable<Peripheral>.create { [weak self] observer in | |||
public func cancelPeripheralConnection(_ peripheral: Peripheral) -> Observable<(Peripheral, BluetoothError?)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could introduce a wrapper type to indicate that the peripheral might be returned without error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by that? Optional type indicates that there may or may not be an error related to disconnection. How would you name your wrapper type? Will it be an enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking through library i found that in most cases a tuple is used instead of wrapper type. I decided to follow the current style. Don't you think that optionality on BluetoothError
indicates enough that the observable can return without error?
@@ -265,7 +265,7 @@ public class BluetoothManager { | |||
strongSelf.centralManager.cancelPeripheralConnection(peripheral.peripheral) | |||
return disposable | |||
} | |||
return ensure(.poweredOn, observable: observable).asSingle() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason for dropping the Single
here? Can we emit multiple events now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Already repairing it.
Source/BluetoothManager.swift
Outdated
public func monitorDisconnection(for peripheral: Peripheral) -> Observable<(Peripheral, BluetoothError?)> { | ||
return monitorPeripheral( | ||
on: delegateWrapper.rx_didDisconnectPeripheral.map { (_, error) in | ||
throw BluetoothError.peripheralDisconnectionFailed(peripheral, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might not read it correctly, but is there a reason for why you're ignoring the peripheral returned from peripheralAction
observable here? It seems to me that the logic deciding which instance should be returned in the error should be kept in one place and monitorPeripheral
is better place in my opinion. Right now it's been done twice: in monitorDisconnection
method and monitorPeripheral
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is not behaving correctly. We shouldn't throw error there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. In the issue I said that error should be emitted in the resulting observable next events, not as an error on stream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
corrected throwing. It should be mapped as you mentioned.
Source/BluetoothManager.swift
Outdated
@@ -255,8 +255,8 @@ public class BluetoothManager { | |||
/// - parameter peripheral: The `Peripheral` to which the `BluetoothManager` is either trying to | |||
/// connect or has already connected. | |||
/// - returns: `Single` which emits next event when peripheral successfully cancelled connection. | |||
public func cancelPeripheralConnection(_ peripheral: Peripheral) -> Single<Peripheral> { | |||
let observable = Observable<Peripheral>.create { [weak self] observer in | |||
public func cancelPeripheralConnection(_ peripheral: Peripheral) -> Observable<(Peripheral, BluetoothError?)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by that? Optional type indicates that there may or may not be an error related to disconnection. How would you name your wrapper type? Will it be an enum?
Source/BluetoothManager.swift
Outdated
return monitorPeripheral( | ||
on: delegateWrapper.rx_didConnectPeripheral.map { ($0, nil) }, | ||
peripheral: peripheral | ||
).map { $0.0 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we creating tuple to just drop it at the end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is to use monitorPeripheral
function in both connection and disconnection functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced to this — It's right now kind of artificial way to do this generalization. Could we find some other approach to implement this? This tuple creation reason is complicated and deserves comment at least. The best would be to find other way or just drop helper function.
Source/BluetoothError.swift
Outdated
@@ -78,6 +79,8 @@ extension BluetoothError: CustomStringConvertible { | |||
return "Connection error has occured: \(err?.localizedDescription ?? "-")" | |||
case let .peripheralDisconnected(_, err): | |||
return "Connection error has occured: \(err?.localizedDescription ?? "-")" | |||
case let .peripheralDisconnectionFailed(_, err): | |||
return "Connection error has occured: \(err?.localizedDescription ?? "-")" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to documentation disconnection cannot fail. So there shouldn't be any error related to that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
Source/BluetoothManager.swift
Outdated
public func monitorDisconnection(for peripheral: Peripheral) -> Observable<(Peripheral, BluetoothError?)> { | ||
return monitorPeripheral( | ||
on: delegateWrapper.rx_didDisconnectPeripheral.map { (_, error) in | ||
throw BluetoothError.peripheralDisconnectionFailed(peripheral, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is not behaving correctly. We shouldn't throw error there.
Source/BluetoothManager.swift
Outdated
} | ||
|
||
func monitorPeripheral(on peripheralAction: Observable<CBPeripheral>, peripheral: Peripheral) | ||
-> Observable<Peripheral> { | ||
func monitorPeripheral(on peripheralAction: Observable<(CBPeripheral, BluetoothError?)>, peripheral: Peripheral) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this function is worth to share it between connected/disconnected events.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in my opinion it is. If we would like to separate it instead of two easy maps we would have to implement logic of filtering and mapping on stream of pheripheralAction
with ensuring poweredOn state in both function monitorConnection
and monitorDisconnection
Source/Peripheral.swift
Outdated
@@ -92,7 +92,7 @@ public class Peripheral { | |||
/// that physical connection will be closed immediately as well and all pending commands will not be executed. | |||
/// | |||
/// - returns: `Single` which emits next event when peripheral successfully cancelled connection. | |||
public func cancelConnection() -> Single<Peripheral> { | |||
public func cancelConnection() -> Observable<(Peripheral, BluetoothError?)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why observable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of more comments. We're getting there :)
Source/Peripheral.swift
Outdated
@@ -92,7 +92,7 @@ public class Peripheral { | |||
/// that physical connection will be closed immediately as well and all pending commands will not be executed. | |||
/// | |||
/// - returns: `Single` which emits next event when peripheral successfully cancelled connection. | |||
public func cancelConnection() -> Single<Peripheral> { | |||
public func cancelConnection() -> Single<(Peripheral)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need parentheses here.
Source/BluetoothManager.swift
Outdated
@@ -265,7 +265,7 @@ public class BluetoothManager { | |||
strongSelf.centralManager.cancelPeripheralConnection(peripheral.peripheral) | |||
return disposable | |||
} | |||
return ensure(.poweredOn, observable: observable).asSingle() | |||
return ensure(.poweredOn, observable: observable).asSingle().map { $0.0 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move map to the new line for better readability
Source/BluetoothManager.swift
Outdated
/// - Returns: Observable which emits next events when `peripheral` was disconnected. | ||
public func monitorDisconnection(for peripheral: Peripheral) -> Observable<Peripheral> { | ||
return monitorPeripheral(on: delegateWrapper.rx_didDisconnectPeripheral.map { $0.0 }, peripheral: peripheral) | ||
/// - Returns: Observable which emits next events when `peripheral` was disconnected and error which is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say: Returns: Observable which emits next events when `Peripheral` instance was disconnected. It provides optional error which may contain more information about the cause of the disconnection if it wasn't the `cancelConnection` call
Source/BluetoothManager.swift
Outdated
return monitorPeripheral(on: delegateWrapper.rx_didDisconnectPeripheral.map { $0.0 }, peripheral: peripheral) | ||
/// - Returns: Observable which emits next events when `peripheral` was disconnected and error which is | ||
/// a disconnection reason when it was caused by 'peripheral' otherwise it's nil. | ||
public typealias DisconnectionReason = Error? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type alias should be above the documentation comments. Right now docs refer to type alias not to a function. Additionaly it should be DisconnectionReason = Error
. Then in interface user sees immediately that it's optional — without looking at type alias definition.
Source/BluetoothManager.swift
Outdated
func monitorPeripheral(on peripheralAction: Observable<CBPeripheral>, peripheral: Peripheral) | ||
-> Observable<Peripheral> { | ||
func monitorPeripheral(on peripheralAction: Observable<(CBPeripheral, DisconnectionReason)>, peripheral: Peripheral) | ||
-> Observable<(Peripheral, Error?)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also use DisconnectionReason here instead of an Error
Source/BluetoothManager.swift
Outdated
return monitorPeripheral( | ||
on: delegateWrapper.rx_didConnectPeripheral.map { ($0, nil) }, | ||
peripheral: peripheral | ||
).map { $0.0 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced to this — It's right now kind of artificial way to do this generalization. Could we find some other approach to implement this? This tuple creation reason is complicated and deserves comment at least. The best would be to find other way or just drop helper function.
…pealias instead of BluetoothError
62b3a11
to
57a1192
Compare
Resolves #170 so the library returns error on monitorDisconnection to the user