2323 */
2424package org .kohsuke .github ;
2525
26- import static com .fasterxml .jackson .annotation .JsonAutoDetect .Visibility .ANY ;
27- import static com .fasterxml .jackson .annotation .JsonAutoDetect .Visibility .NONE ;
28- import static java .util .logging .Level .FINE ;
29- import static java .net .HttpURLConnection .HTTP_UNAUTHORIZED ;
30- import static org .kohsuke .github .Previews .DRAX ;
31-
26+ import com .fasterxml .jackson .databind .DeserializationFeature ;
27+ import com .fasterxml .jackson .databind .ObjectMapper ;
28+ import com .fasterxml .jackson .databind .introspect .VisibilityChecker .Std ;
29+ import com .infradna .tool .bridge_method_injector .WithBridgeMethods ;
3230import java .io .ByteArrayInputStream ;
3331import java .io .FileNotFoundException ;
3432import java .io .IOException ;
4947import java .util .Map ;
5048import java .util .Set ;
5149import java .util .TimeZone ;
52-
50+ import java . util . concurrent . TimeUnit ;
5351import java .util .logging .Level ;
52+ import java .util .logging .Logger ;
5453import javax .annotation .CheckForNull ;
54+ import javax .annotation .Nonnull ;
5555import org .apache .commons .codec .Charsets ;
5656import org .apache .commons .codec .binary .Base64 ;
5757
58- import com .fasterxml .jackson .databind .DeserializationFeature ;
59- import com .fasterxml .jackson .databind .ObjectMapper ;
60- import com .fasterxml .jackson .databind .introspect .VisibilityChecker .Std ;
61- import com .infradna .tool .bridge_method_injector .WithBridgeMethods ;
62-
63- import javax .annotation .Nonnull ;
64- import java .util .logging .Logger ;
58+ import static com .fasterxml .jackson .annotation .JsonAutoDetect .Visibility .ANY ;
59+ import static com .fasterxml .jackson .annotation .JsonAutoDetect .Visibility .NONE ;
60+ import static java .net .HttpURLConnection .HTTP_UNAUTHORIZED ;
61+ import static java .util .logging .Level .FINE ;
62+ import static org .kohsuke .github .Previews .DRAX ;
6563
6664/**
6765 * Root of the GitHub API.
@@ -94,6 +92,7 @@ public class GitHub {
9492
9593 private final Object headerRateLimitLock = new Object ();
9694 private GHRateLimit headerRateLimit = null ;
95+ private volatile GHRateLimit rateLimit = null ;
9796
9897 /**
9998 * Creates a client API root object.
@@ -296,16 +295,16 @@ public void setConnector(HttpConnector connector) {
296295 */
297296 public GHRateLimit getRateLimit () throws IOException {
298297 try {
299- return retrieve ().to ("/rate_limit" , JsonRateLimit .class ).rate ;
298+ return rateLimit = retrieve ().to ("/rate_limit" , JsonRateLimit .class ).rate ;
300299 } catch (FileNotFoundException e ) {
301300 // GitHub Enterprise doesn't have the rate limit, so in that case
302301 // return some big number that's not too big.
303302 // see issue #78
304303 GHRateLimit r = new GHRateLimit ();
305304 r .limit = r .remaining = 1000000 ;
306- long hours = 1000L * 60 * 60 ;
307- r .reset = new Date (System .currentTimeMillis () + 1 * hours );
308- return r ;
305+ long hour = 60L * 60L ; // this is madness, storing the date as seconds in a Date object
306+ r .reset = new Date (( System .currentTimeMillis () + hour ) / 1000L );
307+ return rateLimit = r ;
309308 }
310309 }
311310
@@ -324,11 +323,33 @@ public GHRateLimit getRateLimit() throws IOException {
324323 * Returns the most recently observed rate limit data or {@code null} if either there is no rate limit
325324 * (for example GitHub Enterprise) or if no requests have been made.
326325 *
327- * @return the most recentlt observed rate limit data or {@code null}.
326+ * @return the most recently observed rate limit data or {@code null}.
328327 */
329328 @ CheckForNull
330329 public GHRateLimit lastRateLimit () {
331- return headerRateLimit ;
330+ synchronized (headerRateLimitLock ) {
331+ return headerRateLimit ;
332+ }
333+ }
334+
335+ /**
336+ * Gets the current rate limit while trying not to actually make any remote requests unless absolutely necessary.
337+ *
338+ * @return the current rate limit data.
339+ * @throws IOException if we couldn't get the current rate limit data.
340+ */
341+ @ Nonnull
342+ public GHRateLimit rateLimit () throws IOException {
343+ synchronized (headerRateLimitLock ) {
344+ if (headerRateLimit != null ) {
345+ return headerRateLimit ;
346+ }
347+ }
348+ GHRateLimit rateLimit = this .rateLimit ;
349+ if (rateLimit == null || rateLimit .getResetDate ().getTime () < System .currentTimeMillis ()) {
350+ rateLimit = getRateLimit ();
351+ }
352+ return rateLimit ;
332353 }
333354
334355 /**
0 commit comments