import { JsonValue } from 'type-fest' ; import { MessengerClient , MessengerTypes } from 'messaging-api-messenger' ; import BatchRequestError from './BatchRequestError' ; import { BatchConfig , BatchErrorResponse , BatchRequest , BatchRequestErrorInfo , QueueItem , } from './types' ; const MAX_BATCH_SIZE = 50 ; const alwaysTrue = ( ) : true => true ; export default class FacebookBatchQueue { /**
     * The queue to store facebook requests.
     */ readonly queue : QueueItem [ ] ; private client : MessengerClient ; private delay : number ; private shouldRetry : ( err : BatchRequestErrorInfo ) => boolean ; private retryTimes : number ; private includeHeaders : boolean ; private timeout : NodeJS . Timeout ; param client param options example constructor ( clientConfig , options = { } ) { this . queue = [ ] ; this . client = new MessengerClient ( clientConfig ) ; this . delay = options . delay ?? 1000 ; this . shouldRetry = options . shouldRetry ?? alwaysTrue ; this . retryTimes = options . retryTimes ?? 0 ; this . includeHeaders = options . includeHeaders ?? true ; this . timeout = setTimeout ( ( ) => this . flush ( ) , this . delay ) ; } param request returns example push < T extends JsonValue = any > ( request ) { const promise = new Promise ( ( resolve , reject ) => { this . queue . push ( { request , resolve , reject } ) ; } ) ; if ( this . queue . length >= MAX_BATCH_SIZE ) { this . flush ( ) ; } return promise as Promise < T > ; } example async flush ( ) { const items = this . queue . splice ( 0 , MAX_BATCH_SIZE ) ; clearTimeout ( this . timeout ) ; this . timeout = setTimeout ( ( ) => this . flush ( ) , this . delay ) ; if ( items . length < 1 ) return ; try { const responses = await this . client . sendBatch ( items . map ( ( item ) => item . request ) , { includeHeaders : this . includeHeaders , } ) ; items . forEach ( ( { request , resolve , reject , retry = 0 } , i ) => { const response = responses [ i ] ; if ( response . code === 200 ) { resolve ( response . body ) ; return ; } const err = { response : response as BatchErrorResponse , request , } ; if ( retry < this . retryTimes && this . shouldRetry ( err ) ) { this . queue . push ( { request , resolve , reject , retry : retry + 1 } ) ; } else { reject ( new BatchRequestError ( err ) ) ; } } ) ; } catch ( err ) { items . forEach ( ( { request , resolve , reject , retry = 0 } ) => { if ( retry < this . retryTimes && this . shouldRetry ( err ) ) { this . queue . push ( { request , resolve , reject , retry : retry + 1 } ) ; } else { reject ( err ) ; } } ) ; } } example stop ( ) { clearTimeout ( this . timeout ) ; } }