Skip to content

Commit

Permalink
Change API a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
kyewei committed Nov 12, 2015
1 parent 7103df0 commit 7ab2f36
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 55 deletions.
2 changes: 1 addition & 1 deletion lib/semian.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def register(name, tickets:, permissions: 0660, timeout: 0, error_threshold:, er
error_timeout: error_timeout,
exceptions: Array(exceptions) + [::Semian::BaseError],
permissions: permissions,
type_namespace: ::Semian::SysV,
implementation: ::Semian::SysV,
)
resource = Resource.new(name, tickets: tickets, permissions: permissions, timeout: timeout)
resources[name] = ProtectedResource.new(resource, circuit_breaker)
Expand Down
16 changes: 6 additions & 10 deletions lib/semian/circuit_breaker.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
module Semian
class CircuitBreaker #:nodoc:
def initialize(name, exceptions:, success_threshold:, error_threshold:, error_timeout:, permissions:, type_namespace:)
def initialize(name, exceptions:, success_threshold:, error_threshold:, error_timeout:, permissions:, implementation:)
@name = name.to_s
@success_count_threshold = success_threshold
@error_count_threshold = error_threshold
@error_timeout = error_timeout
@exceptions = exceptions

@errors = type_namespace::SlidingWindow.new(@error_count_threshold,
@errors = implementation::SlidingWindow.new(max_size: @error_count_threshold,
name: "#{name}_sysv_sliding_window",
permissions: permissions)
@successes = type_namespace::Integer.new(name: "#{name}_sysv_integer",
@successes = implementation::Integer.new(name: "#{name}_sysv_integer",
permissions: permissions)
@state = type_namespace::Enum.new([:closed, :half_open, :open],
@state = implementation::Enum.new(symbol_list: [:closed, :half_open, :open],
name: "#{name}_sysv_enum",
permissions: permissions)
# We do not need to #reset here since initializing is handled like this:
# (0) if data is not shared, then it's zeroed already
# (1) if no one is attached to the memory, zero it
# (2) otherwise, keep the data
end

def acquire
Expand Down Expand Up @@ -59,7 +55,7 @@ def mark_success

def reset
@errors.clear
@successes.value = 0
@successes.reset
close
end

Expand Down Expand Up @@ -115,7 +111,7 @@ def error_timeout_expired?

def push_time(window, duration:, time: Time.now)
@errors.execute_atomically do # Store an integer amount of milliseconds since epoch
window.shift while window.first && Time.at(window.first / 1000) + duration < time
window.shift while window.first && window.first / 1000 + duration < time.to_i
window << (time.to_f * 1000).to_i
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/semian/simple_enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Enum < SharedMemoryObject #:nodoc:
:shared?, :destroy, :acquire_memory_object, :bind_init_fn
private :shared?, :acquire_memory_object, :bind_init_fn

def initialize(symbol_list)
def initialize(symbol_list:)
@integer = Semian::Simple::Integer.new
initialize_lookup(symbol_list)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/semian/simple_integer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ def increment(val = 1)
@value += val
end

def reset
@value = 0
end

def destroy
if shared?
super
Expand Down
8 changes: 3 additions & 5 deletions lib/semian/simple_sliding_window.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class SlidingWindow < SharedMemoryObject #:nodoc:
def_delegators :@window, :size, :pop, :shift, :first, :last
attr_reader :max_size

def initialize(max_size)
def initialize(max_size:)
@max_size = max_size
@window = []
end
Expand All @@ -22,16 +22,14 @@ def resize_to(size)
self
end

def <<(time_ms)
push(time_ms)
end

def push(time_ms)
@window.shift while @window.size >= @max_size
@window << time_ms
self
end

alias_method :<<, :push

def clear
@window = []
self
Expand Down
2 changes: 1 addition & 1 deletion lib/semian/sysv_enum.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Semian
module SysV
class Enum < Semian::Simple::Enum #:nodoc:
def initialize(symbol_list, name:, permissions:)
def initialize(symbol_list:, name:, permissions:)
@integer = Semian::SysV::Integer.new(name: name, permissions: permissions)
initialize_lookup(symbol_list)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/semian/sysv_sliding_window.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Semian
module SysV
class SlidingWindow < Semian::Simple::SlidingWindow #:nodoc:
def initialize(max_size, name:, permissions:)
def initialize(max_size:, name:, permissions:)
data_layout = [:int, :int].concat(Array.new(max_size, :long))
super(max_size) unless acquire_memory_object(name, data_layout, permissions)
end
Expand Down
2 changes: 1 addition & 1 deletion test/simple_enum_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class TestSimpleEnum < MiniTest::Unit::TestCase
CLASS = ::Semian::Simple::Enum

def setup
@enum = CLASS.new([:one, :two, :three])
@enum = CLASS.new(symbol_list: [:one, :two, :three])
end

def teardown
Expand Down
40 changes: 19 additions & 21 deletions test/simple_sliding_window_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class TestSimpleSlidingWindow < MiniTest::Unit::TestCase
CLASS = ::Semian::Simple::SlidingWindow

def setup
@sliding_window = CLASS.new(6)
@sliding_window = CLASS.new(max_size: 6)
@sliding_window.clear
end

Expand All @@ -16,47 +16,45 @@ module SlidingWindowTestCases
def test_sliding_window_push
assert_equal(0, @sliding_window.size)
@sliding_window << 1
assert_correct_first_and_last_and_size(@sliding_window, 1, 1, 1, 6)
assert_sliding_window(@sliding_window, [1], 6)
@sliding_window << 5
assert_correct_first_and_last_and_size(@sliding_window, 1, 5, 2, 6)
assert_sliding_window(@sliding_window, [1, 5], 6)
end

def test_sliding_window_resize
assert_equal(0, @sliding_window.size)
@sliding_window << 1 << 2 << 3 << 4 << 5 << 6
assert_correct_first_and_last_and_size(@sliding_window, 1, 6, 6, 6)
assert_sliding_window(@sliding_window, [1, 2, 3, 4, 5, 6], 6)
@sliding_window.resize_to 6
assert_correct_first_and_last_and_size(@sliding_window, 1, 6, 6, 6)
assert_sliding_window(@sliding_window, [1, 2, 3, 4, 5, 6], 6)
@sliding_window.resize_to 5
assert_correct_first_and_last_and_size(@sliding_window, 2, 6, 5, 5)
assert_sliding_window(@sliding_window, [2, 3, 4, 5, 6], 5)
@sliding_window.resize_to 6
assert_correct_first_and_last_and_size(@sliding_window, 2, 6, 5, 6)
assert_sliding_window(@sliding_window, [2, 3, 4, 5, 6], 6)
end

def test_sliding_window_edge_falloff
assert_equal(0, @sliding_window.size)
@sliding_window << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7
assert_correct_first_and_last_and_size(@sliding_window, 2, 7, 6, 6)
assert_sliding_window(@sliding_window, [2, 3, 4, 5, 6, 7], 6)
@sliding_window.shift
assert_correct_first_and_last_and_size(@sliding_window, 3, 7, 5, 6)
assert_sliding_window(@sliding_window, [3, 4, 5, 6, 7], 6)
end

def resize_to_less_than_1_raises
assert_raises ArgumentError do
@sliding_window.resize_to 0
end
end
end

module SlidingWindowUtilityMethods
def assert_correct_first_and_last_and_size(sliding_window, first, last, size, max_size)
assert_equal(first, sliding_window.first)
assert_equal(last, sliding_window.last)
assert_equal(size, sliding_window.size)
def assert_sliding_window(sliding_window, array, max_size)
# Get private member, the sliding_window doesn't expose the entire array
data = sliding_window.instance_variable_get("@window")
assert_equal(array, data)
assert_equal(max_size, sliding_window.max_size)
end

def assert_sliding_windows_in_sync(sliding_window_1, sliding_window_2)
# it only exposes ends, size, and max_size, so can only check those
assert_equal(sliding_window_1.first, sliding_window_2.first)
assert_equal(sliding_window_1.last, sliding_window_2.last)
assert_equal(sliding_window_1.size, sliding_window_2.size)
assert_equal(sliding_window_1.max_size, sliding_window_2.max_size)
end
end

include SlidingWindowTestCases
Expand Down
6 changes: 3 additions & 3 deletions test/sysv_enum_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class << self
end
self.resources = {}
attr_accessor :name
def self.new(symbol_list, name:, permissions:)
def self.new(symbol_list:, name:, permissions:)
obj = resources[name] ||= super
obj.name = name
obj
Expand All @@ -26,7 +26,7 @@ def shared?
CLASS = ::Semian::SysV::Enum

def setup
@enum = CLASS.new([:one, :two, :three],
@enum = CLASS.new(symbol_list: [:one, :two, :three],
name: 'TestAtomicEnum',
permissions: 0660)
end
Expand All @@ -41,7 +41,7 @@ def test_memory_is_shared
assert_equal :one, @enum.value
@enum.value = :three

enum_2 = CLASS.new([:one, :two, :three],
enum_2 = CLASS.new(symbol_list: [:one, :two, :three],
name: 'TestAtomicEnum',
permissions: 0660)
assert_equal :three, enum_2.value
Expand Down
File renamed without changes.
41 changes: 30 additions & 11 deletions test/sysv_sliding_window_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class << self
end
self.resources = {}
attr_accessor :name
def self.new(max_size, name:, permissions:)
def self.new(max_size:, name:, permissions:)
obj = resources[name] ||= super
obj.name = name
obj.resize_to(max_size)
Expand All @@ -27,7 +27,7 @@ def shared?
CLASS = ::Semian::SysV::SlidingWindow

def setup
@sliding_window = CLASS.new(6,
@sliding_window = CLASS.new(max_size: 6,
name: 'TestSlidingWindow',
permissions: 0660)
@sliding_window.clear
Expand All @@ -46,7 +46,7 @@ def test_forcefully_killing_worker_holding_on_to_semaphore_releases_it
end

pid = fork do
sliding_window_2 = CLASS.new(6,
sliding_window_2 = CLASS.new(max_size: 6,
name: 'TestSlidingWindow',
permissions: 0660)
sliding_window_2.execute_atomically { sleep }
Expand All @@ -64,7 +64,7 @@ def test_forcefully_killing_worker_holding_on_to_semaphore_releases_it

def test_sliding_window_memory_is_actually_shared
assert_equal 0, @sliding_window.size
sliding_window_2 = CLASS.new(6,
sliding_window_2 = CLASS.new(max_size: 6,
name: 'TestSlidingWindow',
permissions: 0660)
assert_equal 0, sliding_window_2.size
Expand All @@ -84,14 +84,14 @@ def test_sliding_window_memory_is_actually_shared

def test_restarting_worker_should_not_reset_queue
@sliding_window << 10 << 20 << 30
sliding_window_2 = CLASS.new(6,
sliding_window_2 = CLASS.new(max_size: 6,
name: 'TestSlidingWindow',
permissions: 0660)
assert_correct_first_and_last_and_size(@sliding_window, 10, 30, 3, 6)
sliding_window_2.pop
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)

sliding_window_3 = CLASS.new(6,
sliding_window_3 = CLASS.new(max_size: 6,
name: 'TestSlidingWindow',
permissions: 0660)
assert_correct_first_and_last_and_size(@sliding_window, 10, 20, 2, 6)
Expand All @@ -104,14 +104,14 @@ def test_restarting_worker_should_not_reset_queue
def test_other_workers_automatically_switching_to_new_memory_resizing_up_or_down
# Test explicit resizing, and resizing through making new memory associations

sliding_window_2 = CLASS.new(4,
sliding_window_2 = CLASS.new(max_size: 4,
name: 'TestSlidingWindow',
permissions: 0660)
sliding_window_2 << 80 << 90 << 100 << 110 << 120
assert_correct_first_and_last_and_size(@sliding_window, 90, 120, 4, 4)
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)

sliding_window_2 = CLASS.new(3,
sliding_window_2 = CLASS.new(max_size: 3,
name: 'TestSlidingWindow',
permissions: 0660)
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)
Expand All @@ -121,7 +121,7 @@ def test_other_workers_automatically_switching_to_new_memory_resizing_up_or_down
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)
assert_correct_first_and_last_and_size(@sliding_window, 110, 120, 2, 2)

sliding_window_2 = CLASS.new(4,
sliding_window_2 = CLASS.new(max_size: 4,
name: 'TestSlidingWindow',
permissions: 0660)
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)
Expand All @@ -132,7 +132,7 @@ def test_other_workers_automatically_switching_to_new_memory_resizing_up_or_down
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)
assert_correct_first_and_last_and_size(@sliding_window, 110, 130, 3, 6)

sliding_window_2 = CLASS.new(2,
sliding_window_2 = CLASS.new(max_size: 2,
name: 'TestSlidingWindow',
permissions: 0660)
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)
Expand All @@ -142,7 +142,7 @@ def test_other_workers_automatically_switching_to_new_memory_resizing_up_or_down
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)
assert_correct_first_and_last_and_size(@sliding_window, 120, 130, 2, 4)

sliding_window_2 = CLASS.new(6,
sliding_window_2 = CLASS.new(max_size: 6,
name: 'TestSlidingWindow',
permissions: 0660)
assert_sliding_windows_in_sync(@sliding_window, sliding_window_2)
Expand All @@ -153,5 +153,24 @@ def test_other_workers_automatically_switching_to_new_memory_resizing_up_or_down

private

def assert_sliding_window(sliding_window, array, max_size)
assert_correct_first_and_last_and_size(sliding_window, array.first, array.last, array.size, max_size)
end

def assert_correct_first_and_last_and_size(sliding_window, first, last, size, max_size)
assert_equal(first, sliding_window.first)
assert_equal(last, sliding_window.last)
assert_equal(size, sliding_window.size)
assert_equal(max_size, sliding_window.max_size)
end

def assert_sliding_windows_in_sync(sliding_window_1, sliding_window_2)
# it only exposes ends, size, and max_size, so can only check those
assert_equal(sliding_window_1.first, sliding_window_2.first)
assert_equal(sliding_window_1.last, sliding_window_2.last)
assert_equal(sliding_window_1.size, sliding_window_2.size)
assert_equal(sliding_window_1.max_size, sliding_window_2.max_size)
end

include TestSimpleSlidingWindow::SlidingWindowUtilityMethods
end

0 comments on commit 7ab2f36

Please sign in to comment.