EdvardM
7/8/2015 - 1:21 PM

Simple buffer which accumulates items until buf size is met or max time exceeded since last flush

Simple buffer which accumulates items until buf size is met or max time exceeded since last flush

class Buffer
  attr_reader :min_buf_size, :min_buf_interval, :last_flushed
  def initialize(min_buf_size = 8, min_buf_interval = 1.0, &block)
    @min_buf_size = min_buf_size
    @min_buf_interval = min_buf_interval

    @buf = []
    @last_flushed = now
    @block = block
  end

  # Add item to buf. Flush buffer if either
  #   * min_buf_interval has passed since last flush OR
  #   * buffer size >= min_buf_size
  def add(item)
    @buf << item

    if flush?
      _flush
    end
  end

  # Override this if you want to use OOP-style inheritance for flushing buf
  def flush(buf)
    # no-op
  end

  # call finish when you want to stop buffering to flush
  # possibly remaining items
  def finish
    _flush if !empty?
  end

  def empty?
    @buf.empty?
  end

  private

  def _flush
    if @block
      @block.call(@buf.dup)
    else
      flush(@buf.dup)
    end

    @buf.clear
    @last_flushed = now
  end

  def flush?
    !empty? && (time_to_flush? || buf_full?)
  end

  def buf_full?
    @buf.size >= @min_buf_size
  end

  def time_to_flush?
    now - @last_flushed >= min_buf_interval
  end

  def now
    Time.now
  end
end