game_of_thrones 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +32 -0
- data/Rakefile +22 -0
- data/Readme.md +35 -0
- data/game_of_thrones.gemspec +12 -0
- data/lib/game_of_thrones.rb +48 -0
- data/lib/game_of_thrones/version.rb +3 -0
- data/spec/game_of_thrones_spec.rb +63 -0
- data/spec/spec_helper.rb +5 -0
- metadata +74 -0
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
game_of_thrones (0.1.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (3.2.3)
|
10
|
+
i18n (~> 0.6)
|
11
|
+
multi_json (~> 1.0)
|
12
|
+
diff-lcs (1.1.3)
|
13
|
+
i18n (0.6.0)
|
14
|
+
multi_json (1.3.4)
|
15
|
+
rake (0.9.2)
|
16
|
+
rspec (2.6.0)
|
17
|
+
rspec-core (~> 2.6.0)
|
18
|
+
rspec-expectations (~> 2.6.0)
|
19
|
+
rspec-mocks (~> 2.6.0)
|
20
|
+
rspec-core (2.6.4)
|
21
|
+
rspec-expectations (2.6.0)
|
22
|
+
diff-lcs (~> 1.1.2)
|
23
|
+
rspec-mocks (2.6.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
activesupport (> 3)
|
30
|
+
game_of_thrones!
|
31
|
+
rake
|
32
|
+
rspec (~> 2)
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
task :default do
|
4
|
+
sh "rspec spec/"
|
5
|
+
end
|
6
|
+
|
7
|
+
# extracted from https://github.com/grosser/project_template
|
8
|
+
rule /^version:bump:.*/ do |t|
|
9
|
+
sh "git status | grep 'nothing to commit'" # ensure we are not dirty
|
10
|
+
index = ['major', 'minor','patch'].index(t.name.split(':').last)
|
11
|
+
file = 'lib/game_of_thrones/version.rb'
|
12
|
+
|
13
|
+
version_file = File.read(file)
|
14
|
+
old_version, *version_parts = version_file.match(/(\d+)\.(\d+)\.(\d+)/).to_a
|
15
|
+
version_parts[index] = version_parts[index].to_i + 1
|
16
|
+
version_parts[2] = 0 if index < 2 # remove patch for minor
|
17
|
+
version_parts[1] = 0 if index < 1 # remove minor for major
|
18
|
+
new_version = version_parts * '.'
|
19
|
+
File.open(file,'w'){|f| f.write(version_file.sub(old_version, new_version)) }
|
20
|
+
|
21
|
+
sh "bundle && git add #{file} Gemfile.lock && git commit -m 'bump version to #{new_version}'"
|
22
|
+
end
|
data/Readme.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
Everybody wants to be king, but only one can win (synchronized via a distributed cache).<br/>
|
2
|
+
Update something everybody depends on without doing it multiple times or using a cron.
|
3
|
+
|
4
|
+
Install
|
5
|
+
=======
|
6
|
+
sudo gem install game_of_thrones
|
7
|
+
Or
|
8
|
+
|
9
|
+
rails plugin install git://github.com/grosser/game_of_thrones.git
|
10
|
+
|
11
|
+
|
12
|
+
Usage
|
13
|
+
=====
|
14
|
+
|
15
|
+
aspirant = GameOfThrones.new(
|
16
|
+
:cache => Rails.cache, # where to store the lock ?
|
17
|
+
:timeout => 60 # if current king does not react the next aspirant will take its place
|
18
|
+
)
|
19
|
+
|
20
|
+
Thread.new do
|
21
|
+
loop do
|
22
|
+
# if there is no king or the old king did not do anything, this yields
|
23
|
+
if aspirant.rise_to_power
|
24
|
+
# do something that should only be done by one
|
25
|
+
end
|
26
|
+
sleep 30 # use a timeout lower then the throne timeout
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Author
|
31
|
+
======
|
32
|
+
[Zendesk](http://zendesk.com)<br/>
|
33
|
+
michael@grosser.it<br/>
|
34
|
+
License: MIT<br/>
|
35
|
+
[](http://travis-ci.org/grosser/game_of_thrones)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
name = "game_of_thrones"
|
3
|
+
require "#{name}/version"
|
4
|
+
|
5
|
+
Gem::Specification.new name, GameOfThrones::VERSION do |s|
|
6
|
+
s.summary = "Everybody wants to be king, but only one can win (synchronized via a distributed cache)"
|
7
|
+
s.authors = ["Michael Grosser"]
|
8
|
+
s.email = "michael@grosser.it"
|
9
|
+
s.homepage = "http://github.com/grosser/#{name}"
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.license = 'MIT'
|
12
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "game_of_thrones/version"
|
2
|
+
|
3
|
+
class GameOfThrones
|
4
|
+
def initialize(options)
|
5
|
+
@options = {
|
6
|
+
:timeout => 10 * 60,
|
7
|
+
:cache_key => "GameOfThrones.",
|
8
|
+
:cache => "You have to set :cache",
|
9
|
+
:mutex_timeout => 0.1
|
10
|
+
}.merge(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def rise_to_power
|
14
|
+
if no_king? or in_power?
|
15
|
+
take_power
|
16
|
+
sleep mutex_timeout # multiple people could try to take power simultaneously
|
17
|
+
in_power?
|
18
|
+
else
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def no_king?
|
26
|
+
not current_king
|
27
|
+
end
|
28
|
+
|
29
|
+
def in_power?
|
30
|
+
current_king == myself
|
31
|
+
end
|
32
|
+
|
33
|
+
def mutex_timeout
|
34
|
+
@options[:mutex_timeout] + (@options[:mutex_timeout] * rand)
|
35
|
+
end
|
36
|
+
|
37
|
+
def take_power
|
38
|
+
@options[:cache].write(@options[:cache_key], myself, :expires_in => @options[:timeout])
|
39
|
+
end
|
40
|
+
|
41
|
+
def current_king
|
42
|
+
@options[:cache].read(@options[:cache_key])
|
43
|
+
end
|
44
|
+
|
45
|
+
def myself
|
46
|
+
@myself ||= "#{Process.pid}-#{object_id}-#{Time.now.to_f}"
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GameOfThrones do
|
4
|
+
let(:cache){ ActiveSupport::Cache::MemoryStore.new }
|
5
|
+
|
6
|
+
def new_game(options={})
|
7
|
+
GameOfThrones.new({:cache => cache, :mutex_timeout => 0.01}.merge(options))
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has a VERSION" do
|
11
|
+
GameOfThrones::VERSION.should =~ /^[\.\da-z]+$/
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#rise_to_power" do
|
15
|
+
it "executes if there is no king" do
|
16
|
+
result = nil
|
17
|
+
if new_game.rise_to_power
|
18
|
+
result = 1
|
19
|
+
end
|
20
|
+
result.should == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "executes if the king is alive" do
|
24
|
+
result = nil
|
25
|
+
if new_game.rise_to_power
|
26
|
+
result = 1
|
27
|
+
end
|
28
|
+
if new_game.rise_to_power
|
29
|
+
result = 2
|
30
|
+
end
|
31
|
+
result.should == 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it "executes if the king died" do
|
35
|
+
result = nil
|
36
|
+
new_game(:timeout => 0.2).rise_to_power do
|
37
|
+
result = 1
|
38
|
+
end
|
39
|
+
sleep 0.3
|
40
|
+
if new_game.rise_to_power
|
41
|
+
result = 2
|
42
|
+
end
|
43
|
+
result.should == 2
|
44
|
+
end
|
45
|
+
|
46
|
+
it "ruling keeps the king in power" do
|
47
|
+
result = nil
|
48
|
+
old_king = new_game(:timeout => 0.2)
|
49
|
+
if old_king.rise_to_power
|
50
|
+
result = 1
|
51
|
+
end
|
52
|
+
sleep 0.15
|
53
|
+
if old_king.rise_to_power
|
54
|
+
result = 2
|
55
|
+
end
|
56
|
+
sleep 0.15
|
57
|
+
if new_game.rise_to_power
|
58
|
+
result = 3
|
59
|
+
end
|
60
|
+
result.should == 2
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: game_of_thrones
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Michael Grosser
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-05-09 00:00:00 Z
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: michael@grosser.it
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- .travis.yml
|
31
|
+
- Gemfile
|
32
|
+
- Gemfile.lock
|
33
|
+
- Rakefile
|
34
|
+
- Readme.md
|
35
|
+
- game_of_thrones.gemspec
|
36
|
+
- lib/game_of_thrones.rb
|
37
|
+
- lib/game_of_thrones/version.rb
|
38
|
+
- spec/game_of_thrones_spec.rb
|
39
|
+
- spec/spec_helper.rb
|
40
|
+
homepage: http://github.com/grosser/game_of_thrones
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
hash: 3
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.24
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Everybody wants to be king, but only one can win (synchronized via a distributed cache)
|
73
|
+
test_files: []
|
74
|
+
|