README.md in suo-0.2.3 vs README.md in suo-0.3.0

- old
+ new

@@ -1,10 +1,10 @@ # Suo [![Build Status](https://travis-ci.org/nickelser/suo.svg?branch=master)](https://travis-ci.org/nickelser/suo) [![Code Climate](https://codeclimate.com/github/nickelser/suo/badges/gpa.svg)](https://codeclimate.com/github/nickelser/suo) [![Test Coverage](https://codeclimate.com/github/nickelser/suo/badges/coverage.svg)](https://codeclimate.com/github/nickelser/suo) [![Gem Version](https://badge.fury.io/rb/suo.svg)](http://badge.fury.io/rb/suo) -:lock: Distributed locks using Memcached or Redis in Ruby. +:lock: Distributed semaphores using Memcached or Redis in Ruby. -Suo provides a very performant distributed lock solution using Compare-And-Set (`CAS`) commands in Memcached, and `WATCH/MULTI` in Redis. It allows locking both single exclusion (a mutex - sharing one resource), and multiple resources. +Suo provides a very performant distributed lock solution using Compare-And-Set (`CAS`) commands in Memcached, and `WATCH/MULTI` in Redis. It allows locking both single exclusion (like a mutex - sharing one resource), as well as multiple resources. ## Installation Add this line to your application’s Gemfile: @@ -16,64 +16,62 @@ ### Basic ```ruby # Memcached -suo = Suo::Client::Memcached.new(connection: "127.0.0.1:11211") +suo = Suo::Client::Memcached.new("foo_resource", connection: "127.0.0.1:11211") # Redis -suo = Suo::Client::Redis.new(connection: {host: "10.0.1.1"}) +suo = Suo::Client::Redis.new("baz_resource", connection: {host: "10.0.1.1"}) # Pre-existing client -suo = Suo::Client::Memcached.new(client: some_dalli_client) +suo = Suo::Client::Memcached.new("bar_resource", client: some_dalli_client) -suo.lock("some_key") do +suo.lock do # critical code here @puppies.pet! end -# The second argument to lock is the number of arguments (defaulting to one - a mutex) -Thread.new { suo.lock("other_key", 2) { puts "One"; sleep 2 } } -Thread.new { suo.lock("other_key", 2) { puts "Two"; sleep 2 } } -Thread.new { suo.lock("other_key", 2) { puts "Three" } } +# The resources argument is the number of resources the semaphore will allow to lock (defaulting to one - a mutex) +suo = Suo::Client::Memcached.new("bar_resource", client: some_dalli_client, resources: 2) +Thread.new { suo.lock{ puts "One"; sleep 2 } } +Thread.new { suo.lock { puts "Two"; sleep 2 } } +Thread.new { suo.lock { puts "Three" } } + # will print "One" "Two", but not "Three", as there are only 2 resources # custom acquisition timeouts (time to acquire) -suo = Suo::Client::Memcached.new(client: some_dalli_client, acquisition_timeout: 1) # in seconds +suo = Suo::Client::Memcached.new("protected_key", client: some_dalli_client, acquisition_timeout: 1) # in seconds # manually locking/unlocking # the return value from lock without a block is a unique token valid only for the current lock # which must be unlocked manually -lock = suo.lock("a_key") +token = suo foo.baz! -suo.unlock("a_key", lock) +suo.unlock(token) # custom stale lock expiration (cleaning of dead locks) -suo = Suo::Client::Redis.new(client: some_redis_client, stale_lock_expiration: 60*5) +suo = Suo::Client::Redis.new("other_key", client: some_redis_client, stale_lock_expiration: 60*5) ``` ### Stale locks "Stale locks" - those acquired more than `stale_lock_expiration` (defaulting to 3600 or one hour) ago - are automatically cleared during any operation on the key (`lock`, `unlock`, `refresh`). The `locked?` method will not return true if only stale locks exist, but will not modify the key itself. To re-acquire a lock in the middle of a block, you can use the refresh method on client. ```ruby -suo = Suo::Client::Redis.new +suo = Suo::Client::Redis.new("foo") # lock is the same token as seen in the manual example, above -suo.lock("foo") do |lock| +suo.lock do |token| 5.times do baz.bar! - suo.refresh("foo", lock) + suo.refresh(token) end end ``` - -## Semaphore - -With multiple resources, Suo acts like a semaphore, but is not strictly a semaphore according to the traditional definition, as the lock acquires ownership. ## TODO - more race condition tests ## History