Replies: 9 comments 10 replies
-
This was my vote, which allows for the users to have some flexibility in configuring the timeout or disabling if need be. I like a default timeout present for a couple of reasons you mention (jetstream deadlock especially) but particularly for predictability. As far as I know, unless you're doing a NATS request that does a lot of work on the other end (big KV operation?), no NATS operation is going to take longer than a couple of seconds. Users wrapping the request in a |
Beta Was this translation helpful? Give feedback.
-
+1 to default timeout with the ability to disable/change it. Among the advantages I see over expecting developers to wrap it in a timeout on their own:
The advantages over being a One disadvantage I see is that because |
Beta Was this translation helpful? Give feedback.
-
Not sure if this makes things less or more clear.. but the Go client (which I consider to be the ultimate source of truth since that's the one maintained as first priority) expects a timeout value as a parameter on all requests:
^^ the above is from the README on the go client. |
Beta Was this translation helpful? Give feedback.
-
Interesting take that timeouts create ergonomic issues—I tend to hold the inverse opinion. That is, I feel like it is an ergonomic issue that Given that I don't see how any production program written with
This would make it hard to write broken programs, while timeouts also remain quite discoverable in docs. All that said, I also feel like this change would need to be paired with concrete Error types. While an ergonomic issue by itself, I would say that timeout errors would commonly be dealt with differently than system errors. |
Beta Was this translation helpful? Give feedback.
-
A while ago, I submitted a PR to async_nats to add Two other cases that come to mind: |
Beta Was this translation helpful? Give feedback.
-
First of all, thank you all for the great feedback! @brooksmtownsend I consider request as part of JetStream operations a separate case from request as a user operation. We can assume proper timeouts for JetStream related requests, but we have no idea how user core NATS requests should behave. That's why I didn't even ask about default timeout for request send as part of JetStream internal API. Timeouts are there. That's also why I asked about Core NATS requests. That part is not as simple :). Most operation in Core NATS cannot hang: they're dispatched to TcpStream. Request is an exception, as it's subscribe paired with published. After what you said so far, it seems that most sensible API would be:
It's not bad, but not great either. @abalmos concrete error types will come soon, but please keep in mind that you can access the underlying error pretty easily with Or, we can follow Go client path and do a breaking change, forcing user to always specify the timeout. It sounds justified, as as said - request is a specific NATS operation that is actually two separate ones: pub and sub. |
Beta Was this translation helpful? Give feedback.
-
Apologies for jumping in a little late in the discussion. A bit philosophical - but i believe that timing out on any i/o bound API call is just a statistical encapsulation of an error that has already occurred. in a perfect world we would get a response saying - "this ain't happening", but that's not the case... one of the things i like about rust and it's like are the way they "force/push" you to handle errors and faults in an ergonomic way - i think this is just an extension of that. My current nats experimental code (which led to pr #607) has lots of helper methods which encapsulate a few different edge cases and situations with a I think that Building on top of that i would have 2 versions of each method:
|
Beta Was this translation helpful? Give feedback.
-
So, let's start with having default timeout on As for request with different timeout for each call, as @stevelr uses that: @stevelr maybe a separate function |
Beta Was this translation helpful? Give feedback.
-
PR available here. |
Beta Was this translation helpful? Give feedback.
-
Context
As the new
async_nats
crate matures, we're working on making it resilient against all kind of network issues.One thing we found is that
jetstream::Context.publish()
needs a timeout, as when library waits for the response, that might be lost if reconnection was happening after publishing request, before receiving response. Resulting in deadlock.That was fixed with default
timeout
andset_timeout()
method onJetstream::Context
.Open topic
That leads us to question: how we would like to handle timeouts in Core NATS requests?
Identical scenario can happen in
async_nats::request()
.Usually we tell the users that in
async
ecosystem in Rust, user is expected to wrap the call intokio::time::timeout
and it works fine, as it cancels the future and cleans up, though the API suddenly became somewhat inconsistent.For now, we left the behaviour as is with rationale:
Jetstream::publish()
callsrequest
internally with the responder beingnats-server
, so an internal mechanism with predictable response time. Having default timeout seems to be "path of least surprise".Client::request()
does not have default timeout, as its up to user to decide if he wants to time it out, how long the other service can respond. Tolerance can be few hundred milliseconds or hours.We might go middle ground - by default do not timeout
async_nats::timeout
, but add option to set it onClient
.User can then either set up the option, or directly wrap request calls in
timeout
.Overloading
request
withrequest_with_timeout
does not sound like a good idea, as we would end up with bunch of those for each kind of method call.Would love to hear community and contributors thoughts on this one!
Pinging some active and recent contributors/users:
@stevelr @MattesWhite @thed0ct0r @neogenie @brooksmtownsend @paulgb @autodidaddict
Everybody's opinion is welcomed though!
6 votes ·
Beta Was this translation helpful? Give feedback.
All reactions