mega_mutex 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,5 +1,7 @@
1
1
  # mega_mutex
2
2
 
3
+ A distributed mutex for Ruby.
4
+
3
5
  ## Why
4
6
 
5
7
  Sometimes I need to do this:
@@ -8,7 +10,7 @@ Sometimes I need to do this:
8
10
  make_more_things
9
11
  end
10
12
 
11
- Sometimes though, if I'm running lots of processes in parallel, I get a race condition that means two of the processes both think there are not enough things. So we go and make some more, even though we don't need to.
13
+ If I'm running several processes in parallel, I can get a race condition that means two of the processes both think there are not enough things. So we go and make some more, even though we don't need to.
12
14
 
13
15
  ## How
14
16
 
@@ -18,7 +20,7 @@ Suppose you have a ThingMaker:
18
20
  include MegaMutex
19
21
 
20
22
  def ensure_just_enough_things
21
- with_cross_process_mutex("ThingMaker Mutex ID") do
23
+ with_distributed_mutex("ThingMaker Mutex ID") do
22
24
  unless enough_things?
23
25
  make_more_things
24
26
  end
@@ -28,7 +30,12 @@ Suppose you have a ThingMaker:
28
30
 
29
31
  Now, thanks to the magic of MegaMutex, you can be sure that all processes trying to run this code will wait their turn, so each one will have the chance to make exactly the right number of things, without anyone else poking their nose in.
30
32
 
31
- ## Configuration
33
+ ## Install
34
+
35
+ sudo gem install mega_mutex
36
+
37
+
38
+ ## Configure
32
39
 
33
40
  MegaMutex uses [memcache-client](http://seattlerb.rubyforge.org/memcache-client/) to store the mutex, so your infrastructure must be set up to use memcache servers.
34
41
 
@@ -38,6 +45,10 @@ By default, MegaMutex will attempt to connect to a memcache on the local machine
38
45
  config.memcache_servers = ['mc1', 'mc2']
39
46
  end
40
47
 
48
+ ## Help
49
+
50
+ MegaMutex was built by the [Songkick.com](http://www.songkick.com) development team. Come chat to us on [#songkick](irc://chat.freenode.net/#songkick) on freenode.net.
51
+
41
52
  ## Copyright
42
53
 
43
54
  Copyright (c) 2009 Songkick.com. See LICENSE for details.
data/Rakefile CHANGED
@@ -5,8 +5,8 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "mega_mutex"
8
- gem.summary = %Q{Cross-process mutex using MemCache}
9
- gem.description = %Q{Cross-process mutex using MemCache}
8
+ gem.summary = %Q{Distributed mutex for Ruby}
9
+ gem.description = %Q{Distributed mutex for Ruby}
10
10
  gem.email = "developers@songkick.com"
11
11
  gem.homepage = "http://github.com/songkick/mega_mutex"
12
12
  gem.authors = ["Matt Johnson", "Matt Wynne"]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -4,7 +4,13 @@ require 'memcache'
4
4
  module MegaMutex
5
5
  class TimeoutError < Exception; end
6
6
 
7
- class CrossProcessMutex
7
+ class DistributedMutex
8
+
9
+ class << self
10
+ def cache
11
+ @cache ||= MemCache.new MegaMutex.configuration.memcache_servers, :namespace => MegaMutex.configuration.namespace
12
+ end
13
+ end
8
14
 
9
15
  def initialize(key, timeout = nil)
10
16
  @key = key
@@ -17,7 +23,7 @@ module MegaMutex
17
23
 
18
24
  def run(&block)
19
25
  @start_time = Time.now
20
- log "Attempting to lock cross-process mutex..."
26
+ log "Attempting to lock mutex..."
21
27
  lock!
22
28
  log "Locked. Running critical section..."
23
29
  yield
@@ -76,7 +82,7 @@ module MegaMutex
76
82
  end
77
83
 
78
84
  def cache
79
- @cache ||= MemCache.new MegaMutex.configuration.memcache_servers, :namespace => MegaMutex.configuration.namespace
85
+ self.class.cache
80
86
  end
81
87
  end
82
- end
88
+ end
data/lib/mega_mutex.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
2
  $:.push File.expand_path(File.dirname(__FILE__)) unless $:.include?(File.expand_path(File.dirname(__FILE__)))
3
- require 'mega_mutex/cross_process_mutex'
3
+ require 'mega_mutex/distributed_mutex'
4
4
 
5
5
  # == Why
6
6
  #
@@ -10,7 +10,7 @@ require 'mega_mutex/cross_process_mutex'
10
10
  # make_more_things
11
11
  # end
12
12
  #
13
- # Sometimes though, if I'm running lots of processes in parallel, I get a race condition that means two of the processes both think there are not enough things. So we go and make some more, even though we don't need to.
13
+ # If I'm running several processes in parallel, I can get a race condition that means two of the processes both think there are not enough things. So we go and make some more, even though we don't need to.
14
14
  #
15
15
  # == How
16
16
  #
@@ -42,7 +42,7 @@ require 'mega_mutex/cross_process_mutex'
42
42
  module MegaMutex
43
43
 
44
44
  def self.get_current_lock(mutex_id)
45
- CrossProcessMutex.new(mutex_id).current_lock
45
+ DistributedMutex.new(mutex_id).current_lock
46
46
  end
47
47
 
48
48
  ##
@@ -53,22 +53,23 @@ module MegaMutex
53
53
  # You can optionally specify a :timeout to control how long to wait for the lock to be released
54
54
  # before raising a MegaMutex::TimeoutError
55
55
  #
56
- # with_cross_process_mutex('my_mutex_id_1234', :timeout => 20) do
56
+ # with_distributed_mutex('my_mutex_id_1234', :timeout => 20) do
57
57
  # do_something!
58
58
  # end
59
- def with_cross_process_mutex(mutex_id, options = {}, &block)
60
- mutex = CrossProcessMutex.new(mutex_id, options[:timeout])
59
+ def with_distributed_mutex(mutex_id, options = {}, &block)
60
+ mutex = DistributedMutex.new(mutex_id, options[:timeout])
61
61
  begin
62
62
  mutex.run(&block)
63
63
  rescue Object => e
64
64
  mega_mutex_insert_into_backtrace(
65
65
  e,
66
- /mega_mutex\.rb.*with_cross_process_mutex/,
66
+ /mega_mutex\.rb.*with_(distributed|cross_process)_mutex/,
67
67
  "MegaMutex lock #{mutex_id}"
68
68
  )
69
69
  raise e
70
70
  end
71
71
  end
72
+ alias :with_cross_process_mutex :with_distributed_mutex
72
73
 
73
74
  # inserts a line into a backtrace at the correct location
74
75
  def mega_mutex_insert_into_backtrace(exception, re, newline)
data/mega_mutex.gemspec CHANGED
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mega_mutex}
8
- s.version = "0.2.0"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matt Johnson", "Matt Wynne"]
12
- s.date = %q{2009-10-26}
13
- s.description = %q{Cross-process mutex using MemCache}
12
+ s.date = %q{2010-02-07}
13
+ s.description = %q{Distributed mutex for Ruby}
14
14
  s.email = %q{developers@songkick.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "lib/mega_mutex.rb",
27
- "lib/mega_mutex/cross_process_mutex.rb",
27
+ "lib/mega_mutex/distributed_mutex.rb",
28
28
  "mega_mutex.gemspec",
29
29
  "spec/lib/mega_mutex_spec.rb",
30
30
  "spec/spec_helper.rb"
@@ -33,10 +33,10 @@ Gem::Specification.new do |s|
33
33
  s.rdoc_options = ["--charset=UTF-8"]
34
34
  s.require_paths = ["lib"]
35
35
  s.rubygems_version = %q{1.3.5}
36
- s.summary = %q{Cross-process mutex using MemCache}
36
+ s.summary = %q{Distributed mutex for Ruby}
37
37
  s.test_files = [
38
- "spec/spec_helper.rb",
39
- "spec/lib/mega_mutex_spec.rb"
38
+ "spec/lib/mega_mutex_spec.rb",
39
+ "spec/spec_helper.rb"
40
40
  ]
41
41
 
42
42
  if s.respond_to? :specification_version then
@@ -43,7 +43,7 @@ module MegaMutex
43
43
  describe "when #{n} blocks try to run at the same instant in the same process" do
44
44
  it "should run each in turn" do
45
45
  n.times do
46
- threads << Thread.new{ with_cross_process_mutex(mutex_id, &@mutually_exclusive_block) }
46
+ threads << Thread.new{ with_distributed_mutex(mutex_id, &@mutually_exclusive_block) }
47
47
  end
48
48
  wait_for_threads_to_finish
49
49
  @errors.should be_empty
@@ -53,14 +53,14 @@ module MegaMutex
53
53
 
54
54
  describe "when the first block raises an exception" do
55
55
  before(:each) do
56
- with_cross_process_mutex(mutex_id) do
56
+ with_distributed_mutex(mutex_id) do
57
57
  raise "Something went wrong in my code"
58
58
  end rescue nil
59
59
  end
60
60
 
61
61
  it "the second block should find that the lock is clear and it can run" do
62
62
  @success = nil
63
- with_cross_process_mutex(mutex_id) do
63
+ with_distributed_mutex(mutex_id) do
64
64
  @success = true
65
65
  end
66
66
  @success.should be_true
@@ -86,8 +86,8 @@ module MegaMutex
86
86
 
87
87
  it "should run each in turn" do
88
88
  pids = []
89
- pids << fork { with_cross_process_mutex(mutex_id, &@mutually_exclusive_block); Kernel.exit! }
90
- pids << fork { with_cross_process_mutex(mutex_id, &@mutually_exclusive_block); Kernel.exit! }
89
+ pids << fork { with_distributed_mutex(mutex_id, &@mutually_exclusive_block); Kernel.exit! }
90
+ pids << fork { with_distributed_mutex(mutex_id, &@mutually_exclusive_block); Kernel.exit! }
91
91
  pids.each{ |p| Process.wait(p) }
92
92
  if File.exists?(@errors_file)
93
93
  raise "Expected no errors but found #{File.read(@errors_file)}"
@@ -105,7 +105,7 @@ module MegaMutex
105
105
  @exception = nil
106
106
  @first_thread_has_started = false
107
107
  threads << Thread.new do
108
- with_cross_process_mutex('foo') do
108
+ with_distributed_mutex('foo') do
109
109
  @first_thread_has_started = true
110
110
  sleep 0.2
111
111
  end
@@ -113,7 +113,7 @@ module MegaMutex
113
113
  threads << Thread.new do
114
114
  sleep 0.1 until @first_thread_has_started
115
115
  begin
116
- with_cross_process_mutex('foo', :timeout => 0.1 ) do
116
+ with_distributed_mutex('foo', :timeout => 0.1 ) do
117
117
  raise 'this code should never run'
118
118
  end
119
119
  rescue Exception => @exception
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mega_mutex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Johnson
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-10-26 00:00:00 +00:00
13
+ date: 2010-02-07 00:00:00 +00:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -33,7 +33,7 @@ dependencies:
33
33
  - !ruby/object:Gem::Version
34
34
  version: 1.1.4
35
35
  version:
36
- description: Cross-process mutex using MemCache
36
+ description: Distributed mutex for Ruby
37
37
  email: developers@songkick.com
38
38
  executables: []
39
39
 
@@ -50,7 +50,7 @@ files:
50
50
  - Rakefile
51
51
  - VERSION
52
52
  - lib/mega_mutex.rb
53
- - lib/mega_mutex/cross_process_mutex.rb
53
+ - lib/mega_mutex/distributed_mutex.rb
54
54
  - mega_mutex.gemspec
55
55
  - spec/lib/mega_mutex_spec.rb
56
56
  - spec/spec_helper.rb
@@ -81,7 +81,7 @@ rubyforge_project:
81
81
  rubygems_version: 1.3.5
82
82
  signing_key:
83
83
  specification_version: 3
84
- summary: Cross-process mutex using MemCache
84
+ summary: Distributed mutex for Ruby
85
85
  test_files:
86
- - spec/spec_helper.rb
87
86
  - spec/lib/mega_mutex_spec.rb
87
+ - spec/spec_helper.rb