-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
download/download.go: try to fix long polling 304 and error #3926
download/download.go: try to fix long polling 304 and error #3926
Conversation
Thank's for quick reply.
PS:
|
download/download.go
Outdated
m := metrics.New() | ||
resp, err := d.download(ctx, m) | ||
resp, err := d.download(ctx, m, longPoll) |
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 idea is we keep the long poll status on the downloader and then we can update oneShot
to return only an error. We would then update the long poll status on the downloader in the oneShot
method like we do for etag
. In the download
method on a 304
, we can simply return d.longPoll
instead of isLongPollSupported(resp.Header)
. Let me know if you have more questions.
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.
Seems look good.
- i need to go out, but i do that tomorrow mornining.
- For testing this, have you any advice ? I need run an embed web server for integration testing or something like 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.
Check out the test cases here for reference.
78c2337
to
f83c08b
Compare
Before i write test, i prefere to be sure i have good behavior: i have little modified the code:
if d.config.Polling.LongPollingTimeoutSeconds != nil {
d.longPollingEnabled = resp.longPoll
} the if enabled long poll only if long polling is enabled in configuration( and not if is supported) I have make some manual test:
i have not detect wrong behavior to fallback between regular and long polling. If it's ok for you, i start a test. |
431db7a
to
70c357b
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.
You seem to be on the right track with these changes. Added some comments.
@@ -206,16 +208,11 @@ func (d *Downloader) loop(ctx context.Context) { | |||
if err != nil { | |||
delay = util.DefaultBackoff(float64(minRetryDelay), float64(*d.config.Polling.MaxDelaySeconds), retry) | |||
} else { | |||
if !longPoll { | |||
if d.config.Polling.LongPollingTimeoutSeconds != 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.
We probably need to keep this check.
download/download.go
Outdated
if d.config.Polling.LongPollingTimeoutSeconds != nil { | ||
d.longPollingEnabled = resp.longPoll | ||
if d.longPollingEnabled != resp.longPoll { | ||
d.logger.Warn(fmt.Sprintf("Long polling mode switch from %t to %t", d.longPollingEnabled, resp.longPoll)) | ||
} | ||
} |
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 just set here. Below should be enough.
d.longPollingEnabled = resp.longPoll
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 you talk about a logger:
- The goal of the this logger: Because the capability of switch at runtime between regular and long pooling, it provide a feedback for user to see in what opa is currently.
- But if you think, it's not good i can remove. No problem
if you talk about if d.config.Polling.LongPollingTimeoutSeconds != nil {
see my next global comment
download/download.go
Outdated
} | ||
|
||
func (d *Downloader) download(ctx context.Context, m metrics.Metrics) (*downloaderResponse, error) { | ||
d.logger.Debug("Download starting.") | ||
|
||
d.client = d.client.WithHeader("If-None-Match", d.etag) | ||
|
||
if d.config.Polling.LongPollingTimeoutSeconds != nil { | ||
if d.longPollingEnabled { |
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.
Not sure why we need to change this loop.
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.
see my next global comment
Thank's for your comment. I try to justify my choice according what i have understand (Don't hesitate to tell me if i have miss something). Fact
for handle the fallback in one way and reverse (as i understand the inital code) to 2 states are needed:
There are some points to highlight:
Code explanation for the code inside
For the code inside
For the code inside
if d.config.Polling.LongPollingTimeoutSeconds != nil {
d.config.Polling.LongPollingTimeoutSeconds = nil
} Is for control how download function should work according the effective long polling mode after fallback.
Once again, if i have miss something, or if something is wrong don't hesitate. Thank for you reponse. |
7404b5a
to
e83bad2
Compare
I finished to read/learn downloader_test.go. I was able to make tests. According what i have understand how the download_test are organized. i have add two 3 functions, instead of modify existing function. This function as small as possible and try to target at maximum the I am available for any comments. |
@@ -2,6 +2,7 @@ | |||
// Use of this source code is governed by an Apache2 | |||
// license that can be found in the LICENSE file. | |||
|
|||
//go:build slow |
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: remove this
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.
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.
Hmm I'd be OK with keeping it. 🤷 It'll come in whenever someone's touching the code with go 1.17, and is thus unavoidable... and the right way forward.
8d10f56
to
d7062d9
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.
This is getting close. Few small comments. Thanks for the changes @floriangasc!
download/download.go
Outdated
if d.config.Polling.LongPollingTimeoutSeconds != nil { | ||
d.longPollingEnabled = resp.longPoll | ||
} |
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 can simply be
d.longPollingEnabled = resp.longPoll
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.
Before i remove the if, i prefere to be sure of something.
Without this if d.config.Polling.LongPollingTimeoutSeconds != nil
d.longPollingEnabled will be match if server support. This if says: if user configure longPolling in opa. In case of user don't want/configure longpolling, there is no reason to change d.longPollingEnabled (no matter of server support or not). In other word, the server support long polling should be considered only d.config.Polling.LongPollingTimeoutSeconds
is defined.
The if can be remove only if this two values (server support long polling, and opa is long polling configured) should be the same. I don't think mix this two notions is good. But if you are sure no problem, let me know, i will remove the if (and change the test i have added).
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 you're using the value of d.longPollingEnabled
in other parts of the code. If user switches from regular
to long
to regular
polling again you'll need to update d.longPollingEnabled
accordingly.
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 have change the code. It's seem's give good result. Can you juste confirme one thing:
- The media type
application/vnd.openpolicyagent.bundles
is only allowed for long polling ? - The media type
application/gzip
can't be used for long polling ?
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.
Only if the server responds with Content-Type: application/vnd.openpolicyagent.bundles
, OPA will use long polling.
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.
oki thanks. (I understood correctly)
d7062d9
to
b48a797
Compare
277efe0
to
81ac1a3
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.
@floriangasc thanks for working through this. Few comments. Can you also please squash/rebase your changes and update the commit message.
server *httptest.Server | ||
etagInResponse bool | ||
longPoll bool | ||
opaVendorMediaTypeEnabled bool |
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.
Why do we need opaVendorMediaTypeEnabled
? Can we do without it ?
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.
longPoll
is good. I think opaVendorMediaTypeEnabled should be a rest of some test i have try. Done.
download/download_test.go
Outdated
@@ -663,6 +766,13 @@ func (t *testServer) handle(w http.ResponseWriter, r *http.Request) { | |||
} | |||
} | |||
|
|||
if (t.opaVendorMediaTypeEnabled) || (t.longPoll && !notModified) { |
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.
Could we simplify this ? Also !notModified
seems a bit weird so we can change that too.
if !notModified {
if t.longPoll {
w.Header().Add("Content-Type", "application/vnd.openpolicyagent.bundles")
} else {
w.Header().Add("Content-Type", "application/gzip")
}
}
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 try to introduce contentTypeShouldBeSend
which is better naming. and i a remove opaVendorMediaTypeEnabled
.
Let me known if it's ok for you.
…ling download/download_test.go: testing about oneShot and download method When 304 content-type should not be send. Fix the download code for switch to regular polling and keep the previous value. Fixes: open-policy-agent#3923 Signed-off-by: Gasc Florian <florian.gasc@gmail.com>
81ac1a3
to
afcb2a8
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.
I think there's just one last thing (see inline in download_test.go
) and then we could merge this.
Thanks for your contribution 👏
@@ -2,6 +2,7 @@ | |||
// Use of this source code is governed by an Apache2 | |||
// license that can be found in the LICENSE file. | |||
|
|||
//go:build slow |
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.
Hmm I'd be OK with keeping it. 🤷 It'll come in whenever someone's touching the code with go 1.17, and is thus unavoidable... and the right way forward.
@srenatus I don't understand what the last thing should be done. Can i give me more precision ? |
Sure thing, sorry: #3926 (comment) from what I understood, the field is no longer needed, is it? |
@floriangasc I hope you don't mind that I've edited the commit message a bit while squashing. Thanks again for this contribution, and thanks for being so persistent, bearing with us for more than a month on this 🚀 👍 |
@srenatus i was very busy during last 2/3 weeks, sorry for delay. « Thanks again for this contribution, and thanks for being so persistent, bearing with us for more than a month on this »: No problem. You have also lot of work. I appreciate all comments: be sure is it is most right/good decision/code :). Feel free to modify commit/code as any you want. I just have no response about the nil pointer in opa when there is a miss configuration between bundle sever and opa. I think better to have a more sefl explain error than a segfault. Thank's to you for all ou work you have done. The code of opa is very easy to read and learn. Opa software solve lot of problem for our in very clean and easy way. In some days/week i will probably come back to you. I wait some feedback from production environment before. Thanks again. |
Signed-off-by: Gasc Florian florian.gasc@gmail.com
Fixes: #3923