import { BaseCounter , ICounter } from './Counter' ; /**
 * 提供分桶计数功能，每个桶统计一定时间间隔内的计数。
 * BucketCounter只保留最近N个时间间隔内的计数，再老的会被丢弃。
 * 同时保存从创建开始到现在的累计计数。
 */ export interface IBucketCounter extends ICounter { /**
     * update the counter to the given bucket
     */ update ( n ? ) ; return getBucketCounts ( ) ; param startTime return getBucketCounts ( startTime ) ; return getBucketInterval ( ) ; } export interface Bucket { timestamp ; count ; } export class BucketDeque { private queue : Array < Bucket > = [ ] ; private current = 0 ; private size = 11 ; constructor ( length = 11 ) { this . size = length ; for ( let i = 0 ; i < length ; i ++ ) { this . queue [ i ] = this . createQueueItem ( ) ; } } protected createQueueItem ( ) { return { timestamp : - 1 , count : 0 , } ; } addLast ( e ) { this . current = ( this . current + 1 ) % this . size ; this . queue [ this . current ] = e ; } peek ( ) { return this . queue [ this . current ] ; } /**
     * Example1:
     *      10:00   10:01  10:02   09:57   09:58   09:59
     *      70      80     90      40      50      60
     *              |       \
     *            startPos  latestIndex
     * Example2:
     *      10:00   09:55  09:56   09:57   09:58   09:59
     *      70      20     30      40      50      60
     *      |                                      |
     *      latestIndex                            startPos
     */ getBucketList ( ) { let length = this . queue . length - 1 ; let bucketList = [ ] ; let startPos = this . current ; let startTs = this . queue [ this . current ] . timestamp ; if ( startPos < 0 ) { startPos = 0 ; } for ( let i = startPos ; i >= 0 && startPos - i < length ; i -- ) { bucketList . push ( this . queue [ i ] ) ; } for ( let i = length ; i > startPos + 1 ; i -- ) { if ( this . queue [ i ] . timestamp > startTs ) { } else { bucketList . push ( this . queue [ i ] ) ; } } return bucketList ; } } export class BucketCounter extends BaseCounter implements IBucketCounter { /**
     * 保存从创建开始累积的计数
     */ private totalCount : ICounter ; /**
     * 保存最近N次的精确计数, 采用环形队列避免数据的挪动
     */ private buckets : BucketDeque ; /**
     * 是否更新总次数
     */ private updateTotalCount : boolean = false ; /**
     * 每一次精确计数的之间的时间间隔，单位秒
     * 只能是 1，5，10, 30, 60 这几个数字
     */ private interval ; constructor ( interval = 1 , numberOfBucket = 10 , updateTotalCount = true ) { super ( ) ; this . totalCount = new BaseCounter ( ) ; this . interval = interval ; this . buckets = new BucketDeque ( numberOfBucket + 1 ) ; this . updateTotalCount = updateTotalCount ; } update ( n = 1 ) { if ( this . updateTotalCount ) { this . totalCount . inc ( n ) ; } let curTs = this . calculateCurrentTimestamp ( Date . now ( ) ) ; let lastBucket = this . buckets . peek ( ) ; if ( curTs > lastBucket . timestamp ) { let newBucket = { count : 0 , timestamp : curTs } ; this . buckets . addLast ( newBucket ) ; lastBucket = newBucket ; } lastBucket . count += n ; } return getBucketCounts ( startTime = 0 ) { let counts = new Map ( ) ; let curTs = this . calculateCurrentTimestamp ( Date . now ( ) ) ; for ( let bucket of this . buckets . getBucketList ( ) ) { if ( 1000 * bucket . timestamp >= startTime && bucket . timestamp <= curTs ) { counts . set ( bucket . timestamp * 1000 , bucket . count ) ; } } return counts ; } private calculateCurrentTimestamp ( timestamp ) { return Math . floor ( Math . floor ( timestamp / 1000 ) / this . interval ) * this . interval ; } getCount ( ) { return < number > this . totalCount . getCount ( ) ; } inc ( n ? ) { this . update ( n ) ; } dec ( n = 1 ) { this . update ( - n ) ; } getBucketInterval ( ) { return this . interval ; } }