-
Couldn't load subscription status.
- Fork 0
feat: context cancellation #5
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
base: master
Are you sure you want to change the base?
Conversation
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.
Nice Arnaud! I definitely like the Context addition 👍
| cancelErr = node.DownloadCancel(cid) | ||
| default: | ||
| // continue | ||
| } |
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.
The way I understand this is that the context cancellation is checked only once and is non-blocking due to the default, after download is started. Would it be better to start a go routine and let it cancel the session so that context cancellation can be monitored continuously?
var cancelErr error
go func() {
<-ctx.Done()
cancelErr = node.DownloadCancel(cid)
}()
_, err = bridge.wait()
if err != nil {
// ...I have one question though. If we call C.cGoCodexDownloadStream, then the context is cancelled and node.DownloadCancel is called, will the resources consumed in C.cGoCodexDownloadStream be cleaned up properly? I also find the ergonomics of the two calls to be oddly different:
C.cGoCodexDownloadStream
node.DownloadCancelBut both seem to go through the thread boundary back to nim. Or maybe I misunderstood something here?
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.
The way I understand this is that the context cancellation is checked only once and is non-blocking due to the default, after download is started. Would it be better to start a go routine and let it cancel the session so that context cancellation can be monitored continuously?
Oh yes you're right, thanks !
will the resources consumed in C.cGoCodexDownloadStream be cleaned up properly?
Yes it will. If there is a cancellation, the stream will be closed, the current call to cGoCodexDownloadStream will generate an error. The bridge.wait() will wait until the error is sent and the resources will be freed thanks to defer bridge.free().
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.
Out of curiosity, does this pattern not work?
var cancelErr error
go func() {
<-ctx.Done()
cancelErr = node.DownloadCancel(cid)
}()
if cancelErr != nil:
// ...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.
Sorry I didn't reply directly to your pattern, but the problem is that the goroutine will leak because it will wait infinitely for cancellation.
We agreed on discord on using defer close(done) to close the goroutine after the function is done.
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.
We agreed on using defer close(done), but we don't need the select. The pattern would be like this:
done := make(chan struct{})
defer close(done)
channelError := make(chan error, 1)
go func() {
select {
case <-ctx.Done():
channelError <- node.DownloadCancel(cid)
case <-done:
// Nothing to do, download finished
}
}()
_, err = bridge.wait()| select { | ||
| case <-ctx.Done(): | ||
| cancelErr = node.UploadCancel(sessionId) | ||
| default: | ||
| // continue | ||
| } |
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.
Same comment as above re: go routine.
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.
Same as above re: no select needed.
…celled after the function is done
…ause it is a sync call
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'll approve now so that once download and upload are changed, this can be merged quickly 👍
| cancelErr = node.DownloadCancel(cid) | ||
| default: | ||
| // continue | ||
| } |
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.
We agreed on using defer close(done), but we don't need the select. The pattern would be like this:
done := make(chan struct{})
defer close(done)
channelError := make(chan error, 1)
go func() {
select {
case <-ctx.Done():
channelError <- node.DownloadCancel(cid)
case <-done:
// Nothing to do, download finished
}
}()
_, err = bridge.wait()| select { | ||
| case <-ctx.Done(): | ||
| cancelErr = node.UploadCancel(sessionId) | ||
| default: | ||
| // continue | ||
| } |
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.
Same as above re: no select needed.
This PR add context and cancellation for
UploadReader,UploadFileandDownloadStream.