@@ -18,9 +18,9 @@ import { nanoid } from "nanoid";
1818import { stripIndents } from "common-tags" ;
1919import { getNodeNetworkException , hasNodeNetworkException , isNodeNetworkException } from '../../errors/NodeErrors.js' ;
2020import { SimpleError } from '../../errors/MSErrors.js' ;
21- import { resourceLimits } from 'worker_threads' ;
2221import { baseFormatPlayObj } from '../../../utils/PlayTransformUtils.js' ;
2322import { IRecordingMSList } from '../../transforms/MusicbrainzTransformer.js' ;
23+ import dayjs , { Dayjs } from 'dayjs' ;
2424
2525export interface SubmitResponse {
2626 payload ?: {
@@ -33,6 +33,8 @@ export interface SubmitResponse {
3333export interface MusicbrainzApiConfig extends MusicbrainzApiConfigData {
3434 api : MusicBrainzApi ,
3535 hostname : string
36+ minRequestIntervalDuration : number
37+ lastRequest : Dayjs
3638}
3739
3840export interface MusicbrainzApiClientConfig {
@@ -66,13 +68,18 @@ export class MusicbrainzApiClient extends AbstractApiClient {
6668 for ( const mbConfig of this . config . apis ) {
6769 const u = normalizeWebAddress ( mbConfig . url ?? MUSICBRAINZ_URL ) ;
6870 let mb = mbMap . get ( u . url . hostname ) ;
71+ const mbApiConfig : Omit < MusicbrainzApiConfig , 'api' > = {
72+ ...mbConfig ,
73+ hostname : u . url . hostname ,
74+ minRequestIntervalDuration : 1000 ,
75+ lastRequest : dayjs ( ) . subtract ( 1000 + 1000 , 'ms' )
76+ }
6977 if ( mb === undefined ) {
7078 const api = new MusicBrainzApi ( {
7179 appName : 'multi-scrobbler' ,
7280 appVersion : version ,
7381 appContactInfo : mbConfig . contact ,
7482 baseUrl : u . url . toString ( ) ,
75- rateLimit : mbConfig . rateLimit ?? [ 1 , 1 ] ,
7683 preRequest : options . logUrl === true || isDebugMode ( ) ? ( method , url , headers ) => {
7784 const cacheKey = this . asyncStore . getStore ( ) ?? nanoid ( ) ;
7885 this . cache . set ( `${ cacheKey } -url` , `${ method } - ${ url } ` ) ;
@@ -84,11 +91,17 @@ export class MusicbrainzApiClient extends AbstractApiClient {
8491 requestTimeout : mbConfig . requestTimeout ?? 6000 ,
8592 retryLimit : 2
8693 } ) ;
87- mbApis [ u . url . hostname ] = { api, ...mbConfig , hostname : u . url . hostname } ;
94+ mbApis [ u . url . hostname ] = {
95+ ...mbApiConfig ,
96+ api,
97+ } ;
8898 mbMap . set ( u . url . hostname , api ) ;
8999 mb = api ;
90100 } else if ( mbApis [ u . url . hostname ] === undefined ) {
91- mbApis [ u . url . hostname ] = { api : mb , ...mbConfig , hostname : u . url . hostname } ;
101+ mbApis [ u . url . hostname ] = {
102+ ...mbApiConfig ,
103+ api : mb ,
104+ } ;
92105 }
93106 }
94107
@@ -127,6 +140,17 @@ export class MusicbrainzApiClient extends AbstractApiClient {
127140 const triedHosts : string [ ] = [ ] ;
128141 while ( ! triedHosts . includes ( apiConfig . hostname ) ) {
129142
143+ // keep track of last request init at and wait until at least 1 second since that
144+ // to help prevent rate limiting
145+ let waitTime = 0 ;
146+ const sinceLast = dayjs ( ) . diff ( apiConfig . lastRequest , 'ms' ) ;
147+ waitTime = Math . max ( 0 , apiConfig . minRequestIntervalDuration - sinceLast ) ;
148+ apiConfig . lastRequest = dayjs ( ) . add ( waitTime , 'ms' ) ;
149+ //this.logger.trace(`Waiting ${waitTime}ms to call ${apiConfig.hostname} request at ${apiConfig.lastRequest.toISOString()}`)
150+ if ( waitTime > 0 ) {
151+ await sleep ( waitTime ) ;
152+ }
153+
130154 try {
131155 const res = await this . callApiEndpoint ( apiConfig . api , func , options ) ;
132156 if ( cacheKey !== undefined ) {
0 commit comments