robinhood 0.0.1.pre → 0.0.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.
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