robinhood 0.0.1.pre → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 913bb9ef8276fd39f9c3ba6f1ad43548091601d9
4
+ data.tar.gz: fbb34da42c7ccc99289a41f5fc38495a9360f373
5
+ SHA512:
6
+ metadata.gz: e09bdea365ad31009265edf0cf7607a0ca47c4b26464a646f35d94a1f556c196c9e3f2fec91297a41968bf1f9a0379adfdfc57adc6ca84b49efc8550a1525de5
7
+ data.tar.gz: 0e1aaae54ee25b24b35addf173a1f26c94bdd04cf9314ec5fade00e944e61ca106196dafd57caca42b700b415d5bb4e6af6a93fb35e0f57e174db61aec7d1d0c
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- rbx
1
+ 2.0.0-p247
data/README.md CHANGED
@@ -1,30 +1,39 @@
1
- # Robinhood
1
+ # Robinhood [![Build Status](https://www.travis-ci.org/codegram/robinhood.png?branch=master)](https://www.travis-ci.org/codegram/robinhood)
2
2
 
3
3
  Robinhood is a DSL for constructing iteration-based synchronous processes
4
4
  (aka can't be run as jobs) in a distributed manner.
5
5
 
6
+ In other words: Robs responsibilities from richer processes and gives them to
7
+ the poor.
8
+
6
9
  It leverages celluloid actors for each process and uses Redis as a locking
7
10
  mechanism to ensure the process is run in a single server.
8
11
 
9
12
  ## Usage
10
13
 
11
14
  ```ruby
12
- Robinhood.setup do
13
- process :assigner, timeout: 10.minutes do
15
+ Robinhood.define do
16
+ redis{ Redis.new(:host => "10.0.1.1", :port => 6380) }
17
+
18
+ process :assigner, throttle: 10 do
14
19
  UserAssigner.process!
15
20
  end
16
21
 
17
- process :sweeper, throttle: 1.minute do
22
+ process :sweeper, throttle: false, timeout: 20 do
18
23
  Sweeper.sweep!
19
24
  end
20
25
  end
26
+
27
+ Robinhood.run
21
28
  ```
22
29
 
23
30
  ## How does it work?
24
31
 
25
32
  Each time a process finishes its execution, the lock is released so any other
26
33
  server (or system process) can execute it again. This ensures it will be
27
- executed in a synchronous manner (one after the other).
34
+ executed in a synchronous manner (one after the other). It also garantees the
35
+ executions will be distributed across the processes (or servers) so if a server
36
+ goes down, the load will be distributed evenly across the rest of them.
28
37
 
29
38
  You can also set a timeout (in case a process hangs for some reason) and a
30
39
  throttling mechanism (so a process can't be re-scheduled before this time has
@@ -0,0 +1,46 @@
1
+ require "celluloid"
2
+ require 'logger'
3
+
4
+ module Robinhood
5
+ # The DSL provides syntax suger on top of Robinhood's runtime. It allows us
6
+ # to define processes in a natural language for the programmer's convenience.
7
+ #
8
+ class DSL
9
+ # Public: Initializes the DSL.
10
+ #
11
+ # runtime - A runtime that will be configured using the DSL.
12
+ def initialize(runtime)
13
+ @runtime = runtime
14
+ end
15
+
16
+ # Public: Adds a process to the runtime.
17
+ #
18
+ # name - The name of the process to be run. Will be used to identify the
19
+ # mutex name across System Processes.
20
+ # options - A set of options that will be passed to the Process.
21
+ # block - A block that will be called each execution of this process.
22
+ #
23
+ # Returns nil.
24
+ def process(name, options = {}, &block)
25
+ @runtime.add_process(name, options, block)
26
+ nil
27
+ end
28
+
29
+ # Public: Allows a redis instance to be used to provide the locking.
30
+ #
31
+ # Example:
32
+ #
33
+ # Robinhood.define do
34
+ # redis{ Redis.new(host: 'foo') }
35
+ # end
36
+ #
37
+ # block - A mandatory block whose result will be assigned to the runtime's
38
+ # redis client.
39
+ #
40
+ # Returns nil.
41
+ def redis
42
+ @runtime.redis = yield
43
+ nil
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ require 'redis-mutex'
2
+
3
+ Redis::Classy.db ||= Redis.new
4
+
5
+ module Robinhood
6
+ class Mutex < Redis::Mutex; end;
7
+ end
@@ -1,14 +1,36 @@
1
1
  require 'celluloid'
2
- require 'redis-mutex'
3
2
  require 'benchmark'
3
+ require 'robinhood/mutex'
4
4
 
5
5
  module Robinhood
6
+ # This class wraps a previously defined process. It's responsible to prevent
7
+ # the same process to be run at the sime time on different System Processes.
8
+ #
9
+ # A Process leverages a Celluloid Actor, so it will spawned in a different
10
+ # thread and communicate with the rest of the system with messages.
6
11
  class Process
7
12
  attr_reader :name, :options
8
13
 
9
14
  include Celluloid
10
15
  include Celluloid::Logger
11
16
 
17
+ finalizer :unlock
18
+
19
+ # Public: Initializes a Process
20
+ #
21
+ # name - A String that will be used as a global identifier. It's
22
+ # important that it is unique, since the locking will be
23
+ # performed this name as scope.
24
+ # options - A Hash of options that configure this Process.
25
+ # :throttle - An Integer that represents the minimum number of
26
+ # seconds that this process will take. In other
27
+ # words, if its execution takes less than that, we'll
28
+ # wait a little bit until it hits the next execution.
29
+ # :timeout - An Integer representing the period of time after
30
+ # which this process' execution will be considered as
31
+ # 'hung' and another execution will take place.
32
+ # block - The block that will be evaluated each time this Process gets
33
+ # executed.
12
34
  def initialize(name, options, block)
13
35
  @name = name
14
36
  @options = options
@@ -16,17 +38,31 @@ module Robinhood
16
38
  async.run
17
39
  end
18
40
 
19
- def run
20
- mutex.lock
41
+ private
21
42
 
22
- time = Benchmark.realtime{ @block.call }
43
+ def run
44
+ return unless lock
23
45
 
24
- sleep(difference) if difference = throttle - time
46
+ begin
47
+ time = Benchmark.realtime{ @block.call }
48
+ if difference = throttle - time
49
+ sleep(difference)
50
+ end
51
+ ensure
52
+ unlock
53
+ end
25
54
  ensure
26
- mutex.unlock
27
55
  async.run
28
56
  end
29
57
 
58
+ def lock
59
+ mutex.lock
60
+ end
61
+
62
+ def unlock
63
+ mutex.unlock
64
+ end
65
+
30
66
  def lock_name
31
67
  "robinhood:#{name}:lock"
32
68
  end
@@ -35,12 +71,16 @@ module Robinhood
35
71
  if (throttle = options[:throttle]) != nil
36
72
  throttle
37
73
  else
38
- 0.1
74
+ 0.05
39
75
  end
40
76
  end
41
77
 
78
+ def timeout
79
+ options[:timeout] || 300
80
+ end
81
+
42
82
  def mutex
43
- @mutex ||= Redis::Mutex.new(lock_name, block: 1, sleep: 0.1, expire: 300)
83
+ @mutex ||= Mutex.new(lock_name, block: 1, sleep: 0.1, expire: timeout)
44
84
  end
45
85
  end
46
86
  end
@@ -0,0 +1,77 @@
1
+ require "celluloid"
2
+ require "robinhood/process"
3
+ require 'robinhood/mutex'
4
+
5
+ module Robinhood
6
+ # A Runtime is responsible of kickstarting a Robinhood's execution, spawning
7
+ # all the processes and configuring the environment.
8
+ class Runtime
9
+ attr_accessor :redis
10
+
11
+ # Public: Initializes a Runtime.
12
+ def initialize
13
+ @processes = []
14
+ end
15
+
16
+ # Public: Schedules a process to be run in this Runtime.
17
+ #
18
+ # name - A String identifying this process.
19
+ # options - A Hash of options that will be passed to the underlying
20
+ # Process.
21
+ # block - The block that will be evaluated in this Process.
22
+ #
23
+ # Returns nil.
24
+ def add_process(name, options, block)
25
+ @processes << [name, options, block]
26
+ nil
27
+ end
28
+
29
+ # Public: Starts the Runtime.
30
+ #
31
+ # options - A hash of options to configure this Runtime's execution.
32
+ # (default: {background: false})
33
+ # :background - True if it runs on the background (doesn't block
34
+ # the main thread), False otherwise.
35
+ #
36
+ # Returns the Runtime.
37
+ def run(options = {})
38
+ setup_supervision_group
39
+ Mutex.db = redis
40
+
41
+ Robinhood.log :info, "Starting Robin Hood: Robbing from the rich and giving to the poor.."
42
+
43
+ @actor = options[:background] ? supervision_group.run! : supervision_group.run
44
+ self
45
+ end
46
+
47
+ # Public: Stops this Runtime.
48
+ #
49
+ # Returns nil.
50
+ def stop
51
+ @actor.finalize if @actor
52
+ nil
53
+ end
54
+
55
+ private
56
+
57
+ def redis
58
+ @redis ||= Redis.new
59
+ end
60
+
61
+ def supervision_group
62
+ @supervision_group ||= Class.new(Celluloid::SupervisionGroup)
63
+ end
64
+
65
+ def setup_supervision_group
66
+ @processes.each do |process|
67
+ name, options, block = process
68
+
69
+ supervision_group.supervise Process,
70
+ as: "robinhood_#{name}",
71
+ args: [name, options, block]
72
+ end
73
+
74
+ @processes = []
75
+ end
76
+ end
77
+ end
@@ -1,3 +1,3 @@
1
1
  module Robinhood
2
- VERSION = "0.0.1.pre"
2
+ VERSION = "0.0.1"
3
3
  end
data/lib/robinhood.rb CHANGED
@@ -1,20 +1,89 @@
1
1
  require "robinhood/version"
2
- require "robinhood/setup"
2
+ require "robinhood/dsl"
3
+ require "robinhood/runtime"
3
4
  require "celluloid/autostart"
4
5
 
5
6
  module Robinhood
6
- def self.setup(options = {}, &block)
7
- @setup ||= Setup.new(options)
8
- @setup.instance_eval(&block)
9
- @setup.start
7
+ # Public: The starting point for Robinhood's DSL.
8
+ #
9
+ # Example:
10
+ #
11
+ # Robinhood.define do
12
+ # redis{ Redis.new(host: 'foobar') }
13
+ #
14
+ # process :ed, timeout: 100 do
15
+ # Balls.process!
16
+ # end
17
+ #
18
+ # process :sweeper, throttle: 5 do
19
+ # Sweeper.sweep!
20
+ # end
21
+ # end
22
+ def self.define(&block)
23
+ dsl.instance_eval(&block) if block
10
24
  end
11
25
 
26
+ # Public: Runs a previously configured Robinhood instance.
27
+ #
28
+ # options - A hash of options to configure the execution.
29
+ # (default: {background: false})
30
+ # :background - True if it has to be run on the background (doesn't
31
+ # block the main thread), False otherwise.
32
+ #
33
+ # Returns nil.
34
+ def self.run(options = {})
35
+ runtime.run(options)
36
+ nil
37
+ end
38
+
39
+ # Public: Stops Robinhood's execution, if it was run on the background.
40
+ #
41
+ # Returns nil.
12
42
  def self.stop
13
- @setup.stop if @setup
43
+ runtime.stop if runtime
44
+ nil
45
+ end
46
+
47
+ # Public: Assigns a Logger to Robinhood where it will output info, debug and
48
+ # error messages.
49
+ #
50
+ # Returns the Logger.
51
+ def self.logger=(logger)
52
+ @logger = logger
53
+ end
54
+
55
+ # Private: Logs messages to the logger.
56
+ #
57
+ # loglevel - The message's log level: :info, :error or :debug
58
+ # message - A String with the message to be logged
59
+ #
60
+ # Returns nil.
61
+ def self.log(loglevel, message)
62
+ logger.send loglevel, message if logger
63
+ nil
14
64
  end
15
65
 
66
+ # Semi-public: Resets robinhood to a clean state. Mostly used on testing.
67
+ #
68
+ # Returns nil.
16
69
  def self.reset!
17
70
  stop
18
- @setup = nil
71
+ @runtime = nil
72
+ end
73
+
74
+ def self.logger
75
+ return @logger if defined?(@logger)
76
+ @logger = Logger.new(STDOUT)
77
+ end
78
+ private_class_method :logger
79
+
80
+ def self.runtime
81
+ @runtime ||= Runtime.new
82
+ end
83
+ private_class_method :runtime
84
+
85
+ def self.dsl
86
+ @dsl ||= DSL.new(runtime)
19
87
  end
88
+ private_class_method :dsl
20
89
  end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+ require "robinhood"
3
+
4
+ describe "Robinhood.define" do
5
+ it "executes a process iteratively until it ends" do
6
+ queue = [1, 2]
7
+
8
+ Robinhood.define do
9
+ process :test do
10
+ queue.pop
11
+ end
12
+ end
13
+
14
+ Robinhood.run(background: true)
15
+
16
+ sleep(0.2)
17
+ expect(queue).to be_empty
18
+ end
19
+
20
+ it "allows setting an arbitrary throttle" do
21
+ throttle = 0.01
22
+
23
+ calls = []
24
+
25
+ method_call = Proc.new do
26
+ calls << Time.now
27
+ end
28
+
29
+ Robinhood.define do
30
+ process :test, throttle: throttle do
31
+ method_call.call
32
+ end
33
+ end
34
+
35
+ Robinhood.run(background: true)
36
+
37
+ sleep(throttle * 5)
38
+
39
+ calls.each_with_index do |call, index|
40
+ if (index + 1) < calls.length
41
+ expect(calls[index + 1] - call).to be > throttle
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+ require "robinhood"
3
+ require "robinhood/dsl"
4
+
5
+ module Robinhood
6
+ describe DSL do
7
+ let(:dsl){ DSL.new(runtime) }
8
+
9
+ describe "#process" do
10
+ let(:runtime){ double(:runtime, add_process: true) }
11
+
12
+ it "adds a process to the runtime" do
13
+ block = Proc.new{}
14
+ dsl.process :test, {foo: :bar}, &block
15
+
16
+ expect(runtime).to have_received(:add_process).
17
+ with(:test, {foo: :bar}, block)
18
+ end
19
+ end
20
+
21
+ describe "#redis" do
22
+ let(:runtime){ double(:runtime, :redis= => true) }
23
+
24
+ it "allows setting a redis client to the runtime" do
25
+ redis = double(:redis)
26
+ dsl.redis{ redis }
27
+
28
+ expect(runtime).to have_received(:redis=).with(redis)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ require "spec_helper"
2
+ require "robinhood"
3
+ require "robinhood/process"
4
+ require 'thread'
5
+
6
+ module Robinhood
7
+ describe Process do
8
+ before do
9
+ Robinhood::Runtime.new.run(background: true)
10
+ end
11
+
12
+ describe "mutual exclusion" do
13
+ it "doesn't allow two of the same processes to run at once" do
14
+ output = []
15
+
16
+ Process.new(:test, {throttle: 0.01}, Proc.new{
17
+ output << :ed
18
+ sleep(0.05)
19
+ output << :ed
20
+ })
21
+
22
+ Process.new(:test, {throttle: 0.01}, Proc.new{
23
+ output << :balls
24
+ sleep(0.05)
25
+ output << :balls
26
+ })
27
+
28
+ sleep(2)
29
+
30
+ (output.length / 2).times.map{|i| i * 2}.each do |index|
31
+ expect(output[index]).to eq(output[index + 1])
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+ require "robinhood"
3
+ require "robinhood/runtime"
4
+ require 'thread'
5
+
6
+ module Robinhood
7
+ describe Runtime do
8
+ let(:runtime){ Robinhood::Runtime.new }
9
+
10
+ describe "#add_process" do
11
+ it "adds a process to be executed on start" do
12
+ runtime.add_process :edballs, {foo: :bar}, Proc.new{}
13
+
14
+ runtime.run(background: true)
15
+
16
+ actor = Celluloid::Actor[:robinhood_edballs]
17
+ expect(actor).to_not be_nil
18
+ expect(actor.options).to include(foo: :bar)
19
+ end
20
+ end
21
+
22
+ describe "#run" do
23
+ it "sets the default redis db for the mutex" do
24
+ redis = double(:redis)
25
+ runtime.redis = redis
26
+ runtime.run(background: true)
27
+
28
+ expect(Mutex.db).to eq(redis)
29
+ end
30
+ end
31
+
32
+ describe "#stop" do
33
+ it "stops the runtime synchronously" do
34
+ runtime.add_process :edballs, {foo: :bar}, Proc.new{}
35
+
36
+ runtime.run(background: true)
37
+ runtime.stop
38
+
39
+ expect(Celluloid::Actor[:robinhood_edballs]).to eq(nil)
40
+ end
41
+ end
42
+ end
43
+ end
data/spec/spec_helper.rb CHANGED
@@ -8,13 +8,13 @@ RSpec.configure do |config|
8
8
  config.formatter = :documentation
9
9
  end
10
10
 
11
- config.before(:each) do
11
+ config.before(:all) do
12
12
  Celluloid.logger = nil
13
- redis = Redis.new
14
- redis.flushdb
13
+ Robinhood.logger = nil
15
14
  end
16
15
 
17
- config.after(:each) do
16
+ config.before(:each) do
18
17
  Robinhood.reset!
18
+ Redis.new.flushdb
19
19
  end
20
20
  end
metadata CHANGED
@@ -1,128 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robinhood
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 6
5
- version: 0.0.1.pre
4
+ version: 0.0.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Josep Jaume
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-10-05 00:00:00.000000000 Z
11
+ date: 2013-10-06 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- version_requirements: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ! '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- none: false
14
+ name: celluloid
21
15
  requirement: !ruby/object:Gem::Requirement
22
16
  requirements:
23
- - - ! '>='
17
+ - - '>='
24
18
  - !ruby/object:Gem::Version
25
19
  version: '0'
26
- none: false
27
- name: celluloid
28
20
  type: :runtime
29
21
  prerelease: false
30
- - !ruby/object:Gem::Dependency
31
22
  version_requirements: !ruby/object:Gem::Requirement
32
23
  requirements:
33
- - - ! '>='
24
+ - - '>='
34
25
  - !ruby/object:Gem::Version
35
26
  version: '0'
36
- none: false
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis-mutex
37
29
  requirement: !ruby/object:Gem::Requirement
38
30
  requirements:
39
- - - ! '>='
31
+ - - '>='
40
32
  - !ruby/object:Gem::Version
41
33
  version: '0'
42
- none: false
43
- name: redis-mutex
44
34
  type: :runtime
45
35
  prerelease: false
46
- - !ruby/object:Gem::Dependency
47
36
  version_requirements: !ruby/object:Gem::Requirement
48
37
  requirements:
49
- - - ~>
38
+ - - '>='
50
39
  - !ruby/object:Gem::Version
51
- version: '1.3'
52
- none: false
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
53
43
  requirement: !ruby/object:Gem::Requirement
54
44
  requirements:
55
45
  - - ~>
56
46
  - !ruby/object:Gem::Version
57
47
  version: '1.3'
58
- none: false
59
- name: bundler
60
48
  type: :development
61
49
  prerelease: false
62
- - !ruby/object:Gem::Dependency
63
50
  version_requirements: !ruby/object:Gem::Requirement
64
51
  requirements:
65
- - - ! '>='
52
+ - - ~>
66
53
  - !ruby/object:Gem::Version
67
- version: '0'
68
- none: false
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
69
57
  requirement: !ruby/object:Gem::Requirement
70
58
  requirements:
71
- - - ! '>='
59
+ - - '>='
72
60
  - !ruby/object:Gem::Version
73
61
  version: '0'
74
- none: false
75
- name: rake
76
62
  type: :development
77
63
  prerelease: false
78
- - !ruby/object:Gem::Dependency
79
64
  version_requirements: !ruby/object:Gem::Requirement
80
65
  requirements:
81
- - - ! '>='
66
+ - - '>='
82
67
  - !ruby/object:Gem::Version
83
68
  version: '0'
84
- none: false
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
- - - ! '>='
73
+ - - '>='
88
74
  - !ruby/object:Gem::Version
89
75
  version: '0'
90
- none: false
91
- name: rspec
92
76
  type: :development
93
77
  prerelease: false
94
- - !ruby/object:Gem::Dependency
95
78
  version_requirements: !ruby/object:Gem::Requirement
96
79
  requirements:
97
- - - ! '>='
80
+ - - '>='
98
81
  - !ruby/object:Gem::Version
99
82
  version: '0'
100
- none: false
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
101
85
  requirement: !ruby/object:Gem::Requirement
102
86
  requirements:
103
- - - ! '>='
87
+ - - '>='
104
88
  - !ruby/object:Gem::Version
105
89
  version: '0'
106
- none: false
107
- name: pry
108
90
  type: :development
109
91
  prerelease: false
110
- - !ruby/object:Gem::Dependency
111
92
  version_requirements: !ruby/object:Gem::Requirement
112
93
  requirements:
113
- - - ! '>='
94
+ - - '>='
114
95
  - !ruby/object:Gem::Version
115
96
  version: '0'
116
- none: false
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry-nav
117
99
  requirement: !ruby/object:Gem::Requirement
118
100
  requirements:
119
- - - ! '>='
101
+ - - '>='
120
102
  - !ruby/object:Gem::Version
121
103
  version: '0'
122
- none: false
123
- name: pry-nav
124
104
  type: :development
125
105
  prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
126
111
  description: Robin hood leverages celluloid actors and redis-mutex to distribute long-lived,
127
112
  single-instance processes across multiple servers.
128
113
  email:
@@ -131,65 +116,53 @@ executables: []
131
116
  extensions: []
132
117
  extra_rdoc_files: []
133
118
  files:
134
- - !binary |-
135
- LmdpdGlnbm9yZQ==
136
- - !binary |-
137
- LnJ1YnktdmVyc2lvbg==
138
- - !binary |-
139
- LnRyYXZpcy55bWw=
140
- - !binary |-
141
- R2VtZmlsZQ==
142
- - !binary |-
143
- TElDRU5TRS50eHQ=
144
- - !binary |-
145
- UkVBRE1FLm1k
146
- - !binary |-
147
- UmFrZWZpbGU=
148
- - !binary |-
149
- bGliL3JvYmluaG9vZC5yYg==
150
- - !binary |-
151
- bGliL3JvYmluaG9vZC9wcm9jZXNzLnJi
152
- - !binary |-
153
- bGliL3JvYmluaG9vZC9zZXR1cC5yYg==
154
- - !binary |-
155
- bGliL3JvYmluaG9vZC92ZXJzaW9uLnJi
156
- - !binary |-
157
- cm9iaW5ob29kLmdlbXNwZWM=
158
- - !binary |-
159
- c3BlYy9hY2NlcHRhbmNlL3NldHVwX3NwZWMucmI=
160
- - !binary |-
161
- c3BlYy9zcGVjX2hlbHBlci5yYg==
119
+ - .gitignore
120
+ - .ruby-version
121
+ - .travis.yml
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - lib/robinhood.rb
127
+ - lib/robinhood/dsl.rb
128
+ - lib/robinhood/mutex.rb
129
+ - lib/robinhood/process.rb
130
+ - lib/robinhood/runtime.rb
131
+ - lib/robinhood/version.rb
132
+ - robinhood.gemspec
133
+ - spec/acceptance/dsl_spec.rb
134
+ - spec/lib/robinhood/dsl_spec.rb
135
+ - spec/lib/robinhood/process_spec.rb
136
+ - spec/lib/robinhood/runtime_spec.rb
137
+ - spec/spec_helper.rb
162
138
  homepage: http://www.codegram.com
163
139
  licenses:
164
140
  - MIT
141
+ metadata: {}
165
142
  post_install_message:
166
143
  rdoc_options: []
167
144
  require_paths:
168
145
  - lib
169
146
  required_ruby_version: !ruby/object:Gem::Requirement
170
147
  requirements:
171
- - - ! '>='
148
+ - - '>='
172
149
  - !ruby/object:Gem::Version
173
- hash: 2002549777813010636
174
- segments:
175
- - 0
176
150
  version: '0'
177
- none: false
178
151
  required_rubygems_version: !ruby/object:Gem::Requirement
179
152
  requirements:
180
- - - ! '>'
153
+ - - '>='
181
154
  - !ruby/object:Gem::Version
182
- version: 1.3.1
183
- none: false
155
+ version: '0'
184
156
  requirements: []
185
157
  rubyforge_project:
186
- rubygems_version: 1.8.25
158
+ rubygems_version: 2.0.3
187
159
  signing_key:
188
- specification_version: 3
160
+ specification_version: 4
189
161
  summary: Robin hood leverages celluloid actors and redis-mutex to distribute long-lived,
190
162
  single-instance processes across multiple servers.
191
163
  test_files:
192
- - !binary |-
193
- c3BlYy9hY2NlcHRhbmNlL3NldHVwX3NwZWMucmI=
194
- - !binary |-
195
- c3BlYy9zcGVjX2hlbHBlci5yYg==
164
+ - spec/acceptance/dsl_spec.rb
165
+ - spec/lib/robinhood/dsl_spec.rb
166
+ - spec/lib/robinhood/process_spec.rb
167
+ - spec/lib/robinhood/runtime_spec.rb
168
+ - spec/spec_helper.rb
@@ -1,54 +0,0 @@
1
- require "robinhood/process"
2
- require "celluloid"
3
-
4
- module Robinhood
5
- class Setup
6
- attr_reader :options
7
-
8
- def initialize(options = {})
9
- @options = options
10
- @processes = []
11
- end
12
-
13
- def process(name, options = {}, &block)
14
- @processes << [name, options, block]
15
- end
16
-
17
- def redis
18
- @redis = yield
19
- end
20
-
21
- def supervision_group
22
- @supervision_group ||= Class.new(Celluloid::SupervisionGroup)
23
- end
24
-
25
- def start
26
- setup_supervision_group
27
- Redis::Classy.db = @redis || Redis.new
28
-
29
- @supervision_group_actor = if options[:background]
30
- supervision_group.run!
31
- else
32
- supervision_group.run
33
- end
34
- end
35
-
36
- def stop
37
- @supervision_group_actor.finalize if @supervision_group_actor
38
- end
39
-
40
- def redis_options
41
- options[:redis] || {}
42
- end
43
-
44
- def setup_supervision_group
45
- @processes.each do |process|
46
- name, options, block = process
47
-
48
- supervision_group.supervise Process,
49
- as: "robinhood_#{name}",
50
- args: [name, options.merge(autostart: true), block]
51
- end
52
- end
53
- end
54
- end
@@ -1,46 +0,0 @@
1
- require "spec_helper"
2
- require "robinhood"
3
-
4
- module Robinhood
5
- describe ".setup" do
6
- it "creates actors for each process" do
7
- Robinhood.setup(background: true) do
8
- process(:ed){}
9
- process(:balls){}
10
- end
11
-
12
- sleep(1)
13
-
14
- expect(Celluloid::Actor[:robinhood_ed]).to_not be_nil
15
- expect(Celluloid::Actor[:robinhood_balls]).to_not be_nil
16
- end
17
-
18
- it "executes a process iteratively until it ends" do
19
- queue = [1, 2]
20
-
21
- Robinhood.setup(background: true) do
22
- process :test do
23
- queue.pop
24
- end
25
- end
26
-
27
- sleep(1)
28
- expect(queue).to be_empty
29
- end
30
-
31
- it "allows setting an arbitrary throttle" do
32
- queue = [1, 2]
33
-
34
- Robinhood.setup(background: true) do
35
- process :test, throttle: 0.5 do
36
- queue.pop
37
- end
38
- end
39
-
40
- sleep(0.2)
41
- expect(queue).not_to be_empty
42
- sleep(1)
43
- expect(queue).to be_empty
44
- end
45
- end
46
- end