mirror of
https://github.com/dkam/suo.git
synced 2025-01-29 07:42:43 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8f8350d1c | ||
|
|
1668756a48 | ||
|
|
74e9e3de75 | ||
|
|
75aad64c08 | ||
|
|
2eb56a8eaa | ||
|
|
d260160618 | ||
|
|
57fad16e4b | ||
|
|
30639cae72 | ||
|
|
89061170ea |
@@ -1,3 +1,6 @@
|
||||
language: ruby
|
||||
rvm:
|
||||
- 2.2.0
|
||||
services:
|
||||
- memcached
|
||||
- redis-server
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
## 0.1.1
|
||||
|
||||
- Use [MessagePack](https://github.com/msgpack/msgpack-ruby) for semaphore serialization.
|
||||
|
||||
|
||||
## 0.1.0
|
||||
|
||||
- First release
|
||||
- First release.
|
||||
|
||||
22
LICENSE.txt
Normal file
22
LICENSE.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2015 Nick Elser
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,4 +1,4 @@
|
||||
# Suo
|
||||
# Suo [](https://travis-ci.org/nickelser/suo)
|
||||
|
||||
:lock: Distributed semaphores using Memcached or Redis in Ruby.
|
||||
|
||||
|
||||
3
Rakefile
3
Rakefile
@@ -1,7 +1,8 @@
|
||||
require "bundler/gem_tasks"
|
||||
require "rake/testtask"
|
||||
|
||||
task default: :test
|
||||
Rake::TestTask.new do |t|
|
||||
t.libs << "test"
|
||||
t.pattern = "test/*_test.rb"
|
||||
t.pattern = "test/**/*_test.rb"
|
||||
end
|
||||
|
||||
@@ -82,14 +82,15 @@ module Suo
|
||||
private
|
||||
|
||||
def serialize_locks(locks)
|
||||
locks.map { |time, token| [time.to_f, token].join(":") }.join(",")
|
||||
MessagePack.pack(locks.map { |time, token| [time.to_f, token] })
|
||||
end
|
||||
|
||||
def deserialize_locks(str)
|
||||
str.split(",").map do |s|
|
||||
time, token = s.split(":", 2)
|
||||
[Time.at(time.to_f), token]
|
||||
def deserialize_locks(val)
|
||||
MessagePack.unpack(val).map do |time, token|
|
||||
[Time.at(time), token]
|
||||
end
|
||||
rescue EOFError => _
|
||||
[]
|
||||
end
|
||||
|
||||
def clear_expired_locks(locks, options)
|
||||
|
||||
@@ -16,7 +16,12 @@ module Suo
|
||||
begin
|
||||
start = Time.now.to_f
|
||||
|
||||
options[:retry_count].times do |i|
|
||||
options[:retry_count].times do
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
val, cas = client.get_cas(key)
|
||||
|
||||
# no key has been set yet; we could simply set it, but would lead to race conditions on the initial setting
|
||||
@@ -38,11 +43,6 @@ module Suo
|
||||
end
|
||||
end
|
||||
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
sleep(rand(options[:retry_delay] * 1000).to_f / 1000)
|
||||
end
|
||||
rescue => _
|
||||
@@ -60,6 +60,11 @@ module Suo
|
||||
start = Time.now.to_f
|
||||
|
||||
options[:retry_count].times do
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
val, cas = client.get_cas(key)
|
||||
|
||||
# much like with initial set - ensure the key is here
|
||||
@@ -76,11 +81,6 @@ module Suo
|
||||
|
||||
break if client.set_cas(key, newval, cas)
|
||||
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
sleep(rand(options[:retry_delay] * 1000).to_f / 1000)
|
||||
end
|
||||
rescue => _
|
||||
@@ -98,6 +98,11 @@ module Suo
|
||||
start = Time.now.to_f
|
||||
|
||||
options[:retry_count].times do
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
val, cas = client.get_cas(key)
|
||||
|
||||
break if val.nil? # lock has expired totally
|
||||
@@ -114,11 +119,6 @@ module Suo
|
||||
|
||||
# another client cleared a token in the interim - try again!
|
||||
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
sleep(rand(options[:retry_delay] * 1000).to_f / 1000)
|
||||
end
|
||||
rescue => boom # rubocop:disable Lint/HandleExceptions
|
||||
|
||||
@@ -17,6 +17,11 @@ module Suo
|
||||
start = Time.now.to_f
|
||||
|
||||
options[:retry_count].times do
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
client.watch(key) do
|
||||
begin
|
||||
val = client.get(key)
|
||||
@@ -41,15 +46,9 @@ module Suo
|
||||
|
||||
break if acquisition_token
|
||||
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
sleep(rand(options[:retry_delay] * 1000).to_f / 1000)
|
||||
end
|
||||
rescue => boom
|
||||
raise boom
|
||||
rescue => _
|
||||
raise Suo::Client::FailedToAcquireLock
|
||||
end
|
||||
|
||||
@@ -65,6 +64,11 @@ module Suo
|
||||
start = Time.now.to_f
|
||||
|
||||
options[:retry_count].times do
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
client.watch(key) do
|
||||
begin
|
||||
val = client.get(key)
|
||||
@@ -87,11 +91,6 @@ module Suo
|
||||
|
||||
break if refreshed
|
||||
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
sleep(rand(options[:retry_delay] * 1000).to_f / 1000)
|
||||
end
|
||||
rescue => _
|
||||
@@ -111,6 +110,11 @@ module Suo
|
||||
options[:retry_count].times do
|
||||
cleared = false
|
||||
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
client.watch(key) do
|
||||
begin
|
||||
val = client.get(key)
|
||||
@@ -144,11 +148,6 @@ module Suo
|
||||
|
||||
break if cleared
|
||||
|
||||
if options[:retry_timeout]
|
||||
now = Time.now.to_f
|
||||
break if now - start > options[:retry_timeout]
|
||||
end
|
||||
|
||||
sleep(rand(options[:retry_delay] * 1000).to_f / 1000)
|
||||
end
|
||||
rescue => boom # rubocop:disable Lint/HandleExceptions
|
||||
|
||||
@@ -6,6 +6,8 @@ require "dalli/cas/client"
|
||||
|
||||
require "redis"
|
||||
|
||||
require "msgpack"
|
||||
|
||||
require "suo/client/errors"
|
||||
require "suo/client/base"
|
||||
require "suo/client/memcached"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Suo
|
||||
VERSION = "0.1.0"
|
||||
VERSION = "0.1.1"
|
||||
end
|
||||
|
||||
13
suo.gemspec
13
suo.gemspec
@@ -1,7 +1,7 @@
|
||||
# coding: utf-8
|
||||
lib = File.expand_path('../lib', __FILE__)
|
||||
lib = File.expand_path("../lib", __FILE__)
|
||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||
require 'suo/version'
|
||||
require "suo/version"
|
||||
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = "suo"
|
||||
@@ -10,12 +10,14 @@ Gem::Specification.new do |spec|
|
||||
spec.email = ["nick.elser@gmail.com"]
|
||||
|
||||
spec.summary = %q(Distributed semaphores using Memcached or Redis.)
|
||||
# spec.description = %q{TODO: Long description}
|
||||
spec.description = %q(Distributed semaphores using Memcached or Redis.)
|
||||
spec.homepage = "https://github.com/nickelser/suo"
|
||||
spec.license = "MIT"
|
||||
|
||||
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
||||
spec.files = `git ls-files -z`.split("\x0")
|
||||
spec.bindir = "bin"
|
||||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
||||
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||
spec.require_paths = ["lib"]
|
||||
|
||||
spec.add_dependency "dalli"
|
||||
@@ -25,4 +27,5 @@ Gem::Specification.new do |spec|
|
||||
spec.add_development_dependency "bundler", "~> 1.5"
|
||||
spec.add_development_dependency "rake", "~> 10.0"
|
||||
spec.add_development_dependency "rubocop", "~> 0.30.0"
|
||||
spec.add_development_dependency "minitest", "~> 5.5.0"
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user