-
Notifications
You must be signed in to change notification settings - Fork 79
=serialization #512 Finish ErrorEnvelope implementation #549
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
Conversation
Motivation: `ErrorEnvelope`'s handling of `Codable` errors not yet implemented. Modifications: Finish implementing `ErrorEnvelope`. Frequently ran into the error below and had to take a different approach. ``` value of protocol type 'Codable' (aka 'Decodable & Encodable') cannot conform to 'Encodable'; only struct/enum/class types can conform to protocols ``` Results: Resolves #512
| internal static let AckOps: SerializerID = .foundationJSON | ||
|
|
||
| internal static let ErrorEnvelope: SerializerID = .foundationJSON | ||
| internal static let BestEffortStringError: SerializerID = .foundationJSON |
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.
It doesn't seem like this change is required but adding them here to be consistent
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.
Right yeah because we default to JSON so it works fine by using it.
Thanks for adding here 👍
| /// By doing this before system startup you can ensure a specific serializer is used for those messages. | ||
| /// Make sure tha other nodes in the system are configured the same way though. | ||
| public mutating func registerCodable<Message: ActorMessage>( | ||
| public mutating func registerCodable<Message: Codable>( |
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.
Unrelated to the PR.
Even though ActorMessage is a type alias of Codable, using Codable explicitly here to better match method name (similar to registerProtobufRepresentable)
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.
Right ok, thankfully I'm able to remove both those specialized functions soon :)
| public typealias CodableError = Error & Codable | ||
|
|
||
| public init<Failure: Error>(_ error: Failure) { | ||
| private let _boxed: BoxedCodableError |
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 think this is cleaner and so we can avoid doing type checks everywhere, plus BestEffortStringError is Codable.
| // FIXME: implement being able to encode and carry Codable errors (!) | ||
| // if let codableError = self.error as? Codable { | ||
| // try container.encode(context.outboundManifest(type(of: self.error as Any)), forKey: .manifest) | ||
| // try container.encode(codableError, forKey: .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 couldn't get this approach to work because Codable is a protocol:
value of protocol type 'Codable' (aka 'Decodable & Encodable') cannot conform to 'Encodable'; only struct/enum/class types can conform to protocols
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.
Right, what you dod though is absolutely right 👍
| throw SerializationError.unableToDeserialize(hint: "Error type \(errorType) is not Codable") | ||
| } | ||
|
|
||
| let errorDecoder = try container.superDecoder(forKey: .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.
Found this by serendipity. Seems to work (according to the tests).
|
Test failure: #550 @swift-server-bot test this please |
| } | ||
|
|
||
| let container = try decoder.container(keyedBy: CodingKeys.self) | ||
| private struct BoxedCodableError: Codable { |
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.
Actually don't need separate type. Removed.
| // FIXME: Needs better impl: https://github.com/apple/swift-distributed-actors/issues/512 | ||
| public struct ErrorEnvelope: Error, ActorMessage { | ||
| public let error: Error | ||
| public typealias CodableError = Error & Codable |
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.
👍
| } | ||
|
|
||
| let errorDecoder = try container.superDecoder(forKey: .error) | ||
| self.codableError = try codableErrorType.init(from: errorDecoder) |
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.
oh interesting
ktoso
left a comment
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.
Awesome, thanks a lot :)
| // FIXME: implement being able to encode and carry Codable errors (!) | ||
| // if let codableError = self.error as? Codable { | ||
| // try container.encode(context.outboundManifest(type(of: self.error as Any)), forKey: .manifest) | ||
| // try container.encode(codableError, forKey: .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.
Right, what you dod though is absolutely right 👍
| internal static let AckOps: SerializerID = .foundationJSON | ||
|
|
||
| internal static let ErrorEnvelope: SerializerID = .foundationJSON | ||
| internal static let BestEffortStringError: SerializerID = .foundationJSON |
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.
Right yeah because we default to JSON so it works fine by using it.
Thanks for adding here 👍
| /// By doing this before system startup you can ensure a specific serializer is used for those messages. | ||
| /// Make sure tha other nodes in the system are configured the same way though. | ||
| public mutating func registerCodable<Message: ActorMessage>( | ||
| public mutating func registerCodable<Message: Codable>( |
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.
Right ok, thankfully I'm able to remove both those specialized functions soon :)
|
|
||
| // errors | ||
| settings.registerCodable(ErrorEnvelope.self) // TODO: can be removed once https://github.com/apple/swift/pull/30318 lands | ||
| settings.registerCodable(BestEffortStringError.self) // TODO: can be removed once https://github.com/apple/swift/pull/30318 lands |
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.
👍
Motivation:
ErrorEnvelope's handling ofCodableerrors not yet implemented.Modifications:
Finish implementing
ErrorEnvelope. Frequently ran into the error below and had to take a different approach.Results:
Resolves #512