Skip to content
This repository has been archived by the owner on Dec 8, 2020. It is now read-only.

Commit

Permalink
Move TriggeredBuffer to its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
binarylogic committed Dec 15, 2016
1 parent 874a310 commit 5065529
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 68 deletions.
69 changes: 1 addition & 68 deletions lib/timber/log_devices/http.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "monitor"
require "msgpack"
require "timber/log_devices/http/triggered_buffer"

module Timber
module LogDevices
Expand All @@ -15,72 +14,6 @@ module LogDevices
# will be triggered. This can be handled with the `:buffer_overflow_handler` option upon
# instantiation, allowing you to write the data to disk, etc. See {#new} for more details.
class HTTP
# Maintains a triggered buffer, where the trigger is {PAYLOAD_LIMIT_BYTES}. Once the buffer
# exceeds this limit it will lock and return that buffer up to that point while still making
# a new buffer available for writes. This ensures that the HTTP client can attempt to deliver
# the buffer contents without blocking execution of the application.
#
# If the overall buffer exceeeds the overall limit (specified by the `:limit_bytes` option),
# then a buffer overflow is triggered. This can be customized using the `:overflow_handler`
# option.
class TriggeredBuffer
DEFAULT_PAYLOAD_LIMIT_BYTES = 5_000_000 # 5mb, the Timber API will not accept messages larger than this
DEFAULT_LIMIT_BYTES = 50_000_000 # 50mb

def initialize(options = {})
@buffers = []
@monitor = Monitor.new
@payload_limit_bytes = options[:payload_limit_bytes] || DEFAULT_PAYLOAD_LIMIT_BYTES
@limit_bytes = options[:limit_bytes] || DEFAULT_LIMIT_BYTES
@overflow_handler = options[:overflow_handler]
end

def write(msg)
if msg.bytesize > @payload_limit_bytes || (msg.bytesize + total_bytesize) > @limit_bytes
handle_overflow(msg)
return nil
end

@monitor.synchronize do
buffer = writable_buffer
if @buffers == [] || buffer.frozen?
@buffers << msg
nil
elsif (buffer.bytesize + msg.bytesize) > @payload_limit_bytes
@buffers << msg
buffer.freeze
else
buffer << msg
nil
end
end
end

def reserve
@monitor.synchronize do
buffer = writable_buffer
if buffer
buffer.freeze
end
end
end

private
def total_bytesize
@buffers.reduce(0) { |acc, buffer| acc + buffer.bytesize }
end

def writable_buffer
@buffers.find { |buffer| !buffer.frozen? }
end

def handle_overflow(msg)
if @overflow_handler
@overflow_handler.call(msg)
end
end
end

API_URI = URI.parse("https://api.timber.io/http_frames")
CONTENT_TYPE = "application/x-timber-msgpack-frame-1".freeze
CONNECTION_HEADER = "keep-alive".freeze
Expand Down
73 changes: 73 additions & 0 deletions lib/timber/log_devices/http/triggered_buffer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require "monitor"

module Timber
module LogDevices
class HTTP
# Maintains a triggered buffer, where the trigger is {PAYLOAD_LIMIT_BYTES}. Once the buffer
# exceeds this limit it will lock and return that buffer up to that point while still making
# a new buffer available for writes. This ensures that the HTTP client can attempt to deliver
# the buffer contents without blocking execution of the application.
#
# If the overall buffer exceeeds the overall limit (specified by the `:limit_bytes` option),
# then a buffer overflow is triggered. This can be customized using the `:overflow_handler`
# option.
class TriggeredBuffer
DEFAULT_PAYLOAD_LIMIT_BYTES = 5_000_000 # 5mb, the Timber API will not accept messages larger than this
DEFAULT_LIMIT_BYTES = 50_000_000 # 50mb

def initialize(options = {})
@buffers = []
@monitor = Monitor.new
@payload_limit_bytes = options[:payload_limit_bytes] || DEFAULT_PAYLOAD_LIMIT_BYTES
@limit_bytes = options[:limit_bytes] || DEFAULT_LIMIT_BYTES
@overflow_handler = options[:overflow_handler]
end

def write(msg)
if msg.bytesize > @payload_limit_bytes || (msg.bytesize + total_bytesize) > @limit_bytes
handle_overflow(msg)
return nil
end

@monitor.synchronize do
buffer = writable_buffer
if @buffers == [] || buffer.frozen?
@buffers << msg
nil
elsif (buffer.bytesize + msg.bytesize) > @payload_limit_bytes
@buffers << msg
buffer.freeze
else
buffer << msg
nil
end
end
end

def reserve
@monitor.synchronize do
buffer = writable_buffer
if buffer
buffer.freeze
end
end
end

private
def total_bytesize
@buffers.reduce(0) { |acc, buffer| acc + buffer.bytesize }
end

def writable_buffer
@buffers.find { |buffer| !buffer.frozen? }
end

def handle_overflow(msg)
if @overflow_handler
@overflow_handler.call(msg)
end
end
end
end
end
end

0 comments on commit 5065529

Please sign in to comment.