-
Notifications
You must be signed in to change notification settings - Fork 311
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
Fix handling of AsNs streams #863
Fix handling of AsNs streams #863
Conversation
Blocked by #858 |
ddfa012
to
b8d8770
Compare
Coverage decreased (-0.02%) to 73.086% when pulling 14938da4d01b5bd9b5fce8abab2dec9113535ef6 on rvolosatovs:fix/as-ns-close into 14be53a on TheThingsNetwork:master. |
c4b397e
to
dfeb42f
Compare
dfeb42f
to
14938da
Compare
14938da
to
383ff8c
Compare
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.
Can't we simply use builtin context cancellation? That supports waiting as well
@johanstokking can you clarify what you mean exactly and how it would work? |
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 I don't get it but this implementation is not obvious to me.
How would
LinkApplication
determine ifio.EOF
should be returned orctx.Error()
?
If you want to differentiate between the client closing the context (context.Canceled
) and another link replacing the current (io.EOF
), use pkg/errorcontext
.
In order for this approach to work,
LinkApplication
would need to maintain 2 completely separate contexts andClose()
would need to be responsible for deleting the stream from the map. I don't see benefits of such approach, whereas the proposed solution is simpler and more efficient.
Why two separate contexts? It's the same thing right? You derive a cancelable context from the link context, and that context can be canceled (potentially with a custom error) by a new link.
// First read succeeds when either closeCh is closed by LinkApplication or LinkApplication initializes closing sequence. | ||
// Second read succeeds when closeCh is closed by LinkApplication. | ||
<-s.closeCh | ||
<-s.closeCh |
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.
So Close()
doesn't close but waits for a close
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 triggers the "closing sequence" in LinkApplication
or returns immediately if it is already closed
return err | ||
case <-ws.closeCh: | ||
return errDuplicateSubscription | ||
case ws.closeCh <- struct{}{}: |
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.
You may have ctx.Done()
so you don't guarantee writing to closeCh
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, that's expected.
The write only succeeds when Close()
is called at least once
Is there a problem with the proposed implementation? After the stream is closed(either via NOTE, 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.
You don't have to explain me how it works because I can read Go code.
People have been writing custom trigger and time-based cancelation code for 7 years before context.Context
became a standard library in 1.7.
Now, I very much prefer using that, because it solves exactly the problem at hand. In fact, it's much simpler because you wait for one context to close instead of switching on some weird channel.
For the record, this is an open source project, and I like to keep code accessible for the community to see what's going on and contribute.
But if you believe that rolling custom stuff for obvious things that are in standard libraries is better or simpler (I disagree on both counts), fine.
for _, cl := range ns.applicationServers { | ||
logger.Debug("Close Application Server link") | ||
if err := cl.Close(); err != nil { | ||
logger.WithError(err).Warn("Failed to close AS link") |
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.
- Consistent component naming,
Application Server
else
forDebug
log below
@johanstokking I simply do not understand how to implement following semantics using
|
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.
Looks ok to me. Are you sure you want to merge all the added debug logs?
pkg/networkserver/grpc_asns.go
Outdated
case <-ws.closeCh: | ||
return errDuplicateSubscription | ||
case ws.closeCh <- struct{}{}: | ||
logger.Debug("Close() is called, close link") |
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.
Inconsistent with debug log above, which uses - close link
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.
Even though it's Debug I would not print code
For the record, I think @rvolosatovs's points justify this "custom" cancelation mechanism. Especially the requirement Close() only returns once the stream is deleted from the map is one that Go doesn't solve. Cancelation is easy, but waiting for cleanup after cancelation is currently impossible with context.Context. From https://dave.cheney.net/2017/08/20/context-isnt-for-cancellation:
|
Do you need to wait for that though? Is it even desirable to wait for that? If so, why? |
42dadf5
to
5e93bef
Compare
5e93bef
to
812d07d
Compare
Summary
Fixes handling of As-Ns streams
Changes
Notes for Reviewers
Initially was part of #858