-
Notifications
You must be signed in to change notification settings - Fork 21
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
2.0 API proposal #45
base: main
Are you sure you want to change the base?
2.0 API proposal #45
Conversation
6a29135
to
41e70d0
Compare
cc @fabianfett |
588a098
to
d012743
Compare
I think my biggest feature request for a 2.0 would be to drop the associated Currently proposed protocol: public protocol ServiceDiscovery {
associatedtype Service
associatedtype Instance
func lookup(_ service: Service, deadline: ContinuousClock.Instant?) async throws -> [Instance]
func subscribe(_ service: Service) async throws -> any ServiceDiscoveryInstancesSequence<Instance>
} This means a type that want's to use ServiceDiscovery needs to be generic over three types. Let's assume we want to build a RedisClient that uses ServiceDiscovery: protocol RedisInstance: Hashable {}
final class RedisClient<Discovery: ServiceDiscovery, Service: Hashable, Instance: RedisInstance > {
init(
discovery: Discovery,
service: Service
)
func run() {
for try await instances in self.discovery.subscribe(self.service) {
// do something with the results
}
}
} Personally I think that users should inject the Service into their ServiceDiscovery object on creation. For most usecases you are only interested in one service. And for instances where you are interested in more Services you are always free to use multiple ServiceDiscovery instances. Changed protocol: public protocol ServiceDiscovery {
associatedtype Instance
associatedtype Subscription: AsyncSequence where Subscription.Element == [Instance]
func lookup() async throws -> [Instance]
func subscribe() async throws -> Subscription
} Other changes:
The really cool thing now is the following: Library authors might not need to depend on ServiceDiscovery at all. They can express their requirement completely through AsyncSequences: protocol RedisInstance {}
final class RedisClient<DiscoverySubscription: AsyncSequence> where DiscoverySubscription.Element: Sequence<some RedisInstance> {
init(subscription: DiscoverySubscription)
func run() {
for try await instances in self.subscription {
// do something with the results
}
}
} @tomerd wdyt? |
|
the one thing I am less sure about is removing |
This is true.
In v1 I think we can drop
As described above, the proposed model is very different from that of v1. If we agree on the new model, then yes, I think we can drop |
okay update the proposal @yim-lee @fabianfett. did end up keeping the |
thanks for the ideas and PR @fabianfett, applied! |
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.
Another round of reviews
return nil | ||
} | ||
/// Internal use only | ||
public struct _DiscoverySequence: AsyncSequence { |
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 guess this one is Sendable
?
/// Service discovery instance type | ||
associatedtype Instance: Sendable | ||
/// AsyncSequence of Service discovery instances | ||
associatedtype DiscoverySequence: AsyncSequence where DiscoverySequence.Element == [Instance] |
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.
Do we want to require that the DiscoverySequence
is Sendable
? This will make usage sites much simpler.
|
||
/// Default timeout for lookup. | ||
var defaultLookupTimeout: DispatchTimeInterval { get } | ||
public protocol ServiceDiscovery: Sendable { |
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.
Protocol has the same name as module. ServiceDiscoveryModule
?
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.
Or maybe rename one of them to just Discovery
?
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.
Protocols that describe a capability should be named using the suffixes able, ible, or ing (e.g. Equatable, ProgressReporting).
So ServiceDiscovering?
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 is a thing that can discover services, maybe ServiceDiscoverer
?
Hi! |
@ser-0xff the |
Thank you for the reply. |
d3bd79f
to
f1853b7
Compare
motivation: adopt swift concurrency changes: * replace callback based APIs with swift concurrency and async sequence * remove Mapping wrappers since they are not longer needed and can easy be achieved using conventional functional composition on top of asyn sequence * re-implement in-memory service discover to match the new API * add and adjust tests
Co-authored-by: Yim Lee <[email protected]>
@yim-lee @fabianfett this has been updated per our discussion. the one remaining issue I am aware of is #45 (comment). I dont have a good name atm |
|
||
/// Default timeout for lookup. | ||
var defaultLookupTimeout: DispatchTimeInterval { get } | ||
public protocol ServiceDiscovery: Sendable { |
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.
Or maybe rename one of them to just Discovery
?
Co-authored-by: Yim Lee <[email protected]>
Co-authored-by: Yim Lee <[email protected]>
public protocol ServiceDiscoverySubscription: Sendable { | ||
/// Service discovery instance type | ||
associatedtype Instance: Sendable | ||
/// AsyncSequence of Service discovery instances | ||
associatedtype DiscoverySequence: Sendable, AsyncSequence where DiscoverySequence.Element == Result<[Instance], Error> | ||
|
||
/// - Returns a ``DiscoverySequence``, which is an ``AsyncSequence`` where each of its items is a snapshot listing of service instances. | ||
func next() async -> DiscoverySequence |
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 protocol is a bit weird. I assume your intention is much closer to this:
Let me know what you think :)
Proposal for 2.0 version of the API, based on Swift concurrency