@@ -23,10 +23,12 @@ import (
2323 "go.uber.org/zap"
2424)
2525
26+ const GH_WARN_DUR = 500 // ms
27+
2628// ? https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#about-secondary-rate-limits
2729// no more than 100 parallel requests
28- var ghRtPool = make (chan db.Stream )
29- var ghQlPool = make (chan db.Stream )
30+ var ghRtPool = make (chan db.Stream , 100 )
31+ var ghQlPool = make (chan db.Stream , 100 )
3032var ghTokRt []GHToken // GitHub REST Tokens
3133var ghTokQl []GHToken // GitHub GraphQL Tokens
3234var ghRtTokIdx int = 0
@@ -73,9 +75,9 @@ func (token *GHToken) waitForFish() {
7375// Update token quota and reset time from HTTP response headers
7476func (token * GHToken ) updTok (h http.Header ) {
7577 q , err := strconv .ParseInt (h .Get ("x-ratelimit-remaining" ), 10 , 16 )
76- util .MaybeSuicide (ghl , "strconv x-ratelimit-remaining" , err )
78+ util .MaybeSuicide (ghl , "strconv" , err , zap . String ( " x-ratelimit-remaining" , h . Get ( "x-ratelimit-remaining" )) )
7779 r , err := strconv .ParseInt (h .Get ("x-ratelimit-reset" ), 10 , 64 )
78- util .MaybeSuicide (ghl , "strconv x-ratelimit-reset" , err )
80+ util .MaybeSuicide (ghl , "strconv" , err , zap . String ( " x-ratelimit-reset" , h . Get ( "x-ratelimit-reset" )) )
7981 token .quota = int16 (q )
8082 token .reset = time .Unix (r , 0 )
8183}
@@ -161,18 +163,16 @@ func ghFillTokRt() *GHToken {
161163//
162164// Return the token with the highest quota.
163165func ghFillTokQl () * GHToken {
164- return ghInitTokenPool (& ghTokQl , func (token string ) (GHToken , error ) {
165- var qlcli = ql .NewClient ("https://api.github.com/graphql" , http .DefaultClient ).WithRequestModifier (
166- func (r * http.Request ) {
167- r .Header .Add ("Authorization" , "Bearer " + token )
168- })
166+ return ghInitTokenPool (& ghTokQl , func (token string ) (tok GHToken , err error ) {
167+ tok .key = token
168+ qlcli := tok .qlcli ()
169169 var q struct {
170170 RateLimit struct {
171171 Remaining int16
172172 ResetAt string
173173 }
174174 }
175- err : = qlcli .Query (context .Background (), & q , nil )
175+ err = qlcli .Query (context .Background (), & q , nil )
176176 if err != nil {
177177 return GHToken {}, xerrors .Newf ("query RateLimit -> give up token %s: %w" , token , err )
178178 }
@@ -196,7 +196,7 @@ func GhSwim() chan struct{} {
196196 ready := make (chan struct {}, 1 )
197197 go func () {
198198 for len (ghTokRt ) == 0 || len (ghTokQl ) == 0 {
199- time .Sleep (20 * time .Millisecond )
199+ time .Sleep (1 * time .Millisecond )
200200 }
201201 ready <- struct {}{}
202202 }()
@@ -269,18 +269,36 @@ func ghRtReleaseCall(stream *db.Stream, repo string, token *GHToken) []string {
269269 return []string {}
270270 }
271271 req .Header .Add ("Authorization" , "Bearer " + token .key )
272+ l .Debug ("ghRtReleaseCall" , zap .String ("repo" , repo ))
273+ t0 := time .Now ()
272274 resp , err := http .DefaultClient .Do (req )
275+ if t := time .Since (t0 ); t .Milliseconds () > GH_WARN_DUR {
276+ l .Warn ("took " + t .String ())
277+ }
273278 if util .Yeet (ghl , "resp fail" , err , zap .String ("fetch" , stream .Fetch )) {
274279 return []string {}
275280 }
281+ if resp .StatusCode != http .StatusOK {
282+ body , err := io .ReadAll (resp .Body )
283+ if err != nil {
284+ l .Error ("can't read body" , zap .String ("fetch" , stream .Fetch ), zap .Error (err ))
285+ body = []byte {}
286+ }
287+ l .Error ("bad status" , zap .String ("status" , resp .Status ), zap .String ("fetch" , stream .Fetch ), zap .ByteString ("body" , body ))
288+ return []string {}
289+ }
276290 token .updTok (resp .Header )
277291 buf , err := io .ReadAll (resp .Body )
278292 util .MaybeSuicide (ghl , "can't read buf" , err )
279- var v [] struct {
280- tag_name string
293+ type Resp struct {
294+ Tag string `json:"tag_name"`
281295 }
282- json .Unmarshal (buf , & v )
283- return util .SliceMap (v , func (r struct { tag_name string }) string { return r .tag_name })
296+
297+ var v []Resp
298+ if util .Yeet (l , "can't unmarshal" , json .Unmarshal (buf , & v ), zap .ByteString ("resp" , buf )) {
299+ return []string {}
300+ }
301+ return util .SliceMap (v , func (r Resp ) string { return r .Tag })
284302}
285303
286304// Fetch latest GitHub release using the REST API
@@ -320,16 +338,22 @@ func ghQlTagCall(prefix, owner, name string, len int, qlcli ql.Client, token *GH
320338 } `graphql:"refs(refPrefix: \"refs/tags/\", last: $len, orderBy: {field: TAG_COMMIT_DATE, direction: ASC}, query: $prefix)"`
321339 } `graphql:"repository(owner: $owner, name: $name)"`
322340 }
323- var headers http.Header
324- err := qlcli .Query (context .Background (), & q , map [string ]any {
341+ headers := http.Header {}
342+ l .Debug ("ghQlTagCall" , zap .String ("repo" , owner + "/" + name ))
343+ t0 := time .Now ()
344+ err := qlcli .Query (context .TODO (), & q , map [string ]any {
325345 "prefix" : prefix ,
326346 "owner" : owner ,
327347 "name" : name ,
328348 "len" : len ,
329349 }, ql .BindResponseHeaders (& headers ))
350+ if t := time .Since (t0 ); t .Milliseconds () > GH_WARN_DUR {
351+ l .Warn ("took " + t .String ())
352+ }
330353 if util .Yeet (ghl , "ql_tag_call" , err ) {
331354 return nil
332355 }
356+
333357 tags := make ([]string , 0 , len )
334358 for _ , edge := range q .Repository .Refs .Edges {
335359 tags = append (tags , edge .Node .Name )
@@ -353,7 +377,7 @@ func ghQlTag(stream *db.Stream, remain string, token *GHToken, qlcli ql.Client)
353377 }
354378}
355379
356- const GH_STRM_HDLR_TEST_QL_MAX = 100
380+ const GH_STRM_HDLR_TEST_QL_MAX = 20
357381
358382func GhStrmHdlr (pkg db.Pkg , url string ) * db.Stream {
359383 strm := & db.Stream {
@@ -377,7 +401,8 @@ func GhStrmHdlr(pkg db.Pkg, url string) *db.Stream {
377401 l .Warn ("Found releases, but cannot determine ver/prefix" ,
378402 zap .Strings ("releases" , releases ),
379403 zap .String ("repo" , repo ),
380- zap .String ("pkgid" , pkg .ID .String ()))
404+ zap .String ("pkgid" , pkg .ID .String ()),
405+ zap .String ("pkgv" , pkg .Ver ))
381406 }
382407
383408 tokenql := & ghTokQl [ghQlTokIdx ]
0 commit comments