-
Notifications
You must be signed in to change notification settings - Fork 44
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
ResolvedService: a new plain struct for attributes of a service #302
base: main
Are you sure you want to change the base?
Conversation
@@ -1060,6 +1072,16 @@ pub(crate) fn split_sub_domain(domain: &str) -> (&str, Option<&str>) { | |||
} | |||
} | |||
|
|||
#[non_exhaustive] | |||
pub struct ResolvedService { |
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.
One edge case is: if addresses
is empty in this struct, then it would not be resolved
. Should we call this struct just Service
instead?
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.
If we have decided to split among client and server, we can return an Option
like we are doing right now, indeed Option<ServiceInfo>
can have empty addresses. Therefore, Option<ResolvedService>
could it be a solution?
This approach does not consume |
I made the mistake in the 1st commit, please check the latest one. ;-) |
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 fine for me, thanks a lot! :)
Just a simple nit
@@ -366,6 +366,18 @@ impl ServiceInfo { | |||
.cloned() | |||
.unwrap_or(ServiceStatus::Unknown) | |||
} | |||
|
|||
/// Returns a resolved service instance. | |||
pub fn as_resolved_service(self) -> ResolvedService { |
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.
Nit: Do we use Option<ResolvedService>
for empty addresses?
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 have thought about this, and wanted to keep returning just ResolvedService
for a couple of reasons:
- Better ergonomics for the user. (Having
Option
can complicate many things for the user, in my experience). - Anyway
ResolvedService
struct cannot guarantee its fields are all valid, for example what if.fullname
is empty? So I think we can implement methods inResolvedService
to valid its content, something likeis_valid()
, etc.
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 agree with your points, but I'm a bit confused.
Currently, we retrieve a service client side in this way (just an example with timeout):
while let Ok(event) = receiver.recv_timeout(Duration::from_secs(1)) {
if let ServiceEvent::ServiceResolved(info) = event {
info!("{:?}", info);
}
}
Now we are going to replace info
variable, which is a ServiceInfo
structure, with ResolvedService
. But if there isn't a valid fullname
or an empty vector of addresses
, can't we block all of this before, when we are evaluating the ServiceEvent::ServiceResolved(info)
condition? I mean, we can return a different event
variant when the conditions above are not satisfied. Just talking for the client side.
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.
Now we are going to replace info variable, which is a ServiceInfo structure, with ResolvedService.
Actually I'm not saying to replace info
here. Because such change will break the backward compatibility, we said going with option 1 instead: The user will call info.as_resolved_service
to consume info
and get a ResolvedService
struct.
But if there isn't a valid fullname or an empty vector of addresses, can't we block all of this before, when we are evaluating the ServiceEvent::ServiceResolved(info) condition?
Yes, from this event the info
is always valid, which means ResolvedService
struct will also be valid in this context. But this is a business logic, we can document it but we cannot enforce it (via the type system or compiler).
But for any given ResolvedService
without such context, we would need something like is_valid
(or is_ready
to match the current code in service_info.rs).
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.
Ok, I see now, thank you! The changes are fine for me, and the is_valid
method is a simpler solution, so let's stick with 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.
Thanks! I've updated the diff with a test case and export in lib.rs
. However, I have a new question regarding sub_domain
below. Any suggestions or comments?
e2ccfcc
to
23f3016
Compare
23f3016
to
9f54e37
Compare
/// Consumes self and returns a resolved service, i.e. a lite version of `ServiceInfo`. | ||
pub fn as_resolved_service(self) -> ResolvedService { | ||
ResolvedService { | ||
ty_domain: self.ty_domain, |
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 question: what if this service info has some sub_domain
? Currently, ServiceInfo
stores only the regular service type & domain in ty_domain
, and the full subtype & domain in sub_domain
. Do we want the same thing in ResolvedService
?
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 we should make sub_domain
public too. If we are consuming ServingInfo
, we can transfer it to ResolvedService
. We do not know all kinds of use cases out there, perhaps someone needs that information. If it was public and accessible before, in my opinion, it should be accessible even in ResolvedService
.
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.
ty_domain
and sub_domain
was not public, but they are indeed accessible via a public API (getter). I agree with you, I think it's better to include sub_domain
in ResolvedService
as well.
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.
With public, I meant accessible via public interface :P
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've updated the diff and added sub_ty_domain
. No longer a draft ;-). Let me know if this patch works for you. Thanks!
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.
Thanks a lot! It is fine for me!
Just a small nit, you can merge for me after that
/// This is from a client (i.e. querier) point of view. | ||
#[non_exhaustive] | ||
pub struct ResolvedService { | ||
/// service type and domain. For example, "_http._tcp.local." |
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.
Nit: Shouldn't the comments of this structure capitalized? The sub_ty_domain
is capitalized and even those of functions
This patch is to follow up on the discussions in issue #299.