Skip to content
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

Caching is not working properly with Repositories.GetContents #1503

Closed
m4ns0ur opened this issue Apr 23, 2020 · 11 comments
Closed

Caching is not working properly with Repositories.GetContents #1503

m4ns0ur opened this issue Apr 23, 2020 · 11 comments

Comments

@m4ns0ur
Copy link

m4ns0ur commented Apr 23, 2020

Not sure if it's go-github issue or httpcache one.

I'm trying to cache Repositories.GetContents responses to avoid my rate limit's burning.

package main

import (
	"context"
	"fmt"

	"github.com/google/go-github/github"
	"github.com/gregjones/httpcache"
	"github.com/gregjones/httpcache/diskcache"
)

func main() {
	cl := github.NewClient(httpcache.NewTransport(diskcache.New(".")).Client())
	_, _, r, _ := cl.Repositories.GetContents(context.Background(), "google", "go-github", "LICENSE", nil)
	fmt.Println(r)
}

At first run (diskcache file is going to be created for the first time), it works

$ date && go run main.go 
Thu 23 Apr 2020 02:01:04 PM CEST
&{0xc00014c090 0 0 0 0  github.Rate{Limit:60, Remaining:5, Reset:github.Timestamp{2020-04-23 14:20:15 +0200 CEST}}}
...
$ date && go run main.go 
Thu 23 Apr 2020 02:01:27 PM CEST
&{0xc000114000 0 0 0 0  github.Rate{Limit:60, Remaining:5, Reset:github.Timestamp{2020-04-23 14:20:15 +0200 CEST}}}

But if you run it again, after 60s (Github API's max-age), it doesn't work anymore

$ date && go run main.go 
Thu 23 Apr 2020 02:02:17 PM CEST
&{0xc000112000 0 0 0 0  github.Rate{Limit:60, Remaining:4, Reset:github.Timestamp{2020-04-23 14:20:14 +0200 CEST}}}
...
$ date && go run main.go 
Thu 23 Apr 2020 02:02:19 PM CEST
&{0xc00018a000 0 0 0 0  github.Rate{Limit:60, Remaining:3, Reset:github.Timestamp{2020-04-23 14:20:14 +0200 CEST}}}
@gmlewis
Copy link
Collaborator

gmlewis commented Apr 23, 2020

I see you already found #242 (where I probably would have put this issue).
I've never personally used httpcache and I see in #242 that others have had challenges with it.

I would suggest contacting the httpcache author and see what he recommends, then please report back here (or close this issue and report back in #242... either way is fine with me).

@m4ns0ur
Copy link
Author

m4ns0ur commented Apr 23, 2020

@gmlewis sure! let me try httpcache.
I'll keep this open since #242 could be different.

@m4ns0ur
Copy link
Author

m4ns0ur commented Apr 25, 2020

Update:
httpcache is lazy, and invalidates the cache after full http.body read. The issue is, we never get EOF here in code snippet even though go-github reads the full body.

At first place it was really confusing because it works occasionally! then I noticed, sometimes Github API server sends Transfer-encoding: chunked. Whenever we have chunked, it uses chunkedReader, gets EOF, and invalidates the cache. But without chunked, it uses bufio reader, and misses EOF.

An easy workaround for httpcache would be checking the length beside EOF here.

func (r *cachingReadCloser) Read(p []byte) (n int, err error) {
	n, err = r.R.Read(p)
	r.buf.Write(p[:n])
	if err == io.EOF || n < len(p) {
		r.OnEOF(bytes.NewReader(r.buf.Bytes()))
	}
	return n, err
}

But anyways we should check why bufio doesn't handle EOF.

@gmlewis
Copy link
Collaborator

gmlewis commented Apr 25, 2020

Maybe you could submit a PR to the httpcache repo with the workaround?

Alternatively (or in addition 😄), you could submit a PR to this repo with a unit test demonstrating the bufio EOF problem along with the fix (if I understand you correctly).

Third option - if you could put a tiny-as-possible test case into this issue that demonstrates the bufio EOF problem, I could start looking into a fix.

Thanks for the investigation.

@m4ns0ur
Copy link
Author

m4ns0ur commented Apr 26, 2020

The bufio issue could be in Go, not in go-github (I'm looking into it).
With fixing bufio there is no need to send any PR to httpcache.

@m4ns0ur
Copy link
Author

m4ns0ur commented Apr 26, 2020

It's not a Go issue because document says EOF is optional. I'm sending a PR to fix the issue in httpcache.

Since issue is happening inside JSON decoder (where we read the body), we cannot have a test/PR in this repo, sorry :)

@gmlewis
Copy link
Collaborator

gmlewis commented Apr 26, 2020

OK, sounds good to me. Thanks, @m4ns0ur.
Closing issue.

@gmlewis gmlewis closed this as completed Apr 26, 2020
@m4ns0ur
Copy link
Author

m4ns0ur commented Apr 26, 2020

For reference: gregjones/httpcache#104

@gmlewis
Copy link
Collaborator

gmlewis commented Apr 26, 2020

@m4ns0ur - would that PR you reference also resolve our #242?

@gmlewis
Copy link
Collaborator

gmlewis commented Apr 26, 2020

If so, would you mind referencing your PR in that issue as well?

@m4ns0ur
Copy link
Author

m4ns0ur commented Apr 26, 2020

@gmlewis I don't think so.

saschagrunert added a commit to saschagrunert/release-sdk that referenced this issue Jun 13, 2022
The httpcache transport is breaking authentication where no fix seems to
be implemented yet. I'd propose to revert the change for now to be able
to use authenticated requests in tools like
`k/release/cmd/release-notes`.

Refers to: google/go-github#1503,
gregjones/httpcache#104

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants