File tree Expand file tree Collapse file tree 2 files changed +19
-0
lines changed Expand file tree Collapse file tree 2 files changed +19
-0
lines changed Original file line number Diff line number Diff line change 11import { utcDay , utcYear } from "d3-time" ;
22import { format as formatIso } from "isoformat" ;
33import { fetchCached as fetch } from "./fetch.js" ;
4+ import { RateLimiter } from "./rate.js" ;
45import { today } from "./today.js" ;
56
7+ const rateLimit = RateLimiter ( 30 , 60_000 ) ; // 30 requests per 60 seconds
8+
69export async function fetchNpm ( path ) {
710 const url = new URL ( path , "https://api.npmjs.org" ) ;
811 let response ;
912 let headers ;
1013 for ( let attempt = 0 , maxAttempts = 3 ; attempt < maxAttempts ; ++ attempt ) {
14+ await rateLimit ( ) ;
1115 response = await fetch ( url , { headers : { "User-Agent" : "observablehq/oss-analytics" } } ) ;
1216 headers = response . headers ;
1317 if ( response . ok ) break ;
Original file line number Diff line number Diff line change 1+ export function RateLimiter ( n , duration ) {
2+ let recents = [ ] ;
3+ return async ( ) => {
4+ if ( ! ( ( n = + n ) >= 1 ) ) throw new Error ( `invalid n: ${ n } ` ) ;
5+ while ( true ) {
6+ const time = Date . now ( ) - duration ;
7+ recents = recents . filter ( ( r ) => r >= time ) ;
8+ if ( recents . length < n ) break ;
9+ const delay = Math . max ( recents [ 0 ] + duration - Date . now ( ) , 100 ) ;
10+ console . warn ( `rate limit reached; waiting ${ delay } ` ) ;
11+ await new Promise ( ( resolve ) => setTimeout ( resolve , delay ) ) ;
12+ }
13+ recents . push ( Date . now ( ) ) ;
14+ } ;
15+ }
You can’t perform that action at this time.
0 commit comments