JSFiddle - React, Tailwind, and code Playground

by IceCreamYou

JavaScript

// TODO: docs, tests

function HitCounter() {
	this.hits = [];
  this.lastTimestamp = -1;
}

HitCounter.prototype.getTimestamp = function() {
	return Math.floor(Date.now() / 1000);
};

HitCounter.prototype.hit = function() {
	var now = this.getTimestamp();
  if (now !== this.lastTimestamp) {
  	this.hits.unshift({ hits: 1, timestamp: now });
    this.lastTimestamp = now;
    if (this.hits.length > 300) { // Max 5 minutes at 1 second granularity
    	this.hits.length = 300; // Drop counts past 5 minutes
      // A possible extension would be to "roll up" counts to coarser granularity
    }
  }
  else {
  	this.hits[0].hits++;
  }
};

// Has an error of +/- 1 second
HitCounter.prototype.getHitsInLastNSeconds = function(n) {
	var sum = 0,
  	since = this.getTimestamp() - n;
  for (var i = 0; i < n; i++) {
  	if (this.hits[i]) {
      if (this.hits[i].timestamp > since) {
        sum += this.hits[i].hits;
      }
      else {
        break;
      }
    }
  }
  return sum;
};

var counter = new HitCounter();
for (var i = 0, l = Math.floor(Math.random() * 1000); i < l; i++) {
	counter.hit();
}
console.log(counter.getHitsInLastNSeconds(1));