profit 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -14,9 +14,10 @@ client.stop("some_suspect_code")
14
14
  ```
15
15
 
16
16
  Here's the server
17
- ``` ruby
18
- server = Profit::Server.new
19
- server.run
17
+ ``` shell
18
+ $ profit_server --redis-address 127.0.0.1:6379 \
19
+ --zmq-address tcp://*:5556 \
20
+ --pool-size 10
20
21
  ```
21
22
 
22
23
  And if you looked in Redis
@@ -1,5 +1,27 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'optparse'
3
4
  require 'profit'
4
5
 
5
- Profit::Server.new.run
6
+ options = {}
7
+ OptionParser.new { |opts|
8
+ opts.banner = "Usage: profit_server [options]"
9
+
10
+ opts.on("-r", "--redis-address [STRING]", String,
11
+ "Redis Address (127.0.0.1:6379)") do |ra|
12
+ options[:redis_address] = ra.split(":").first
13
+ options[:redis_port] = ra.split(":").last.to_i
14
+ end
15
+
16
+ opts.on("-z", "--zmq-address [STRING]", String,
17
+ "ZMQ Address (tcp://*:5556)") do |za|
18
+ options[:zmq_address] = za
19
+ end
20
+
21
+ opts.on("-n", "--pool-size [DECIMAL]", OptionParser::DecimalInteger,
22
+ "Redis client pool size (10)") do |n|
23
+ options[:pool_size] = n
24
+ end
25
+ }.parse!
26
+
27
+ Profit::Server.new(options).run
@@ -1,11 +1,10 @@
1
1
  require 'zmq'
2
2
  require 'eventmachine'
3
- require 'redis'
3
+ require 'em-hiredis'
4
4
  require 'json'
5
5
 
6
6
  module Profit
7
7
  end
8
8
 
9
- require 'profit/message_handler'
10
9
  require 'profit/server'
11
10
  require 'profit/client'
@@ -4,64 +4,68 @@ module Profit
4
4
 
5
5
  attr_reader :ctx
6
6
 
7
- def initialize
7
+ def initialize(options = {})
8
+ @options = {}
9
+ @options[:redis_address] = options[:redis_address] || "127.0.0.1"
10
+ @options[:redis_port] = options[:redis_port] || 6379
11
+ @options[:zmq_address] = options[:zmq_address] || "tcp://*:5556"
12
+ @options[:pool_size] = options[:pool_size] || 10
8
13
  @ctx = ZMQ::Context.new
9
14
  end
10
15
 
11
- def shutdown!
12
- @shutdown = true
13
- end
14
-
15
- def setup_trap_int
16
- trap :INT do
17
- puts "\nSIGINT received, quitting!"
18
- EM.stop
19
- end
20
- end
21
-
22
16
  def run
23
- @run = true
24
17
  EM.run do
25
18
 
26
- @redis_pool = EM::Pool.new
27
- spawn = lambda { @redis_pool.add Redis.new(host: "127.0.0.1", port: 6379) }
28
- @redis_pool.on_error { |conn| spawn[] }
29
- 10.times { spawn[] }
30
-
31
- @puller = @ctx.bind(:PULL, "tcp://127.0.0.1:5556")
19
+ # startup the EM::Hiredis connections
20
+ spawn_redis_connections
32
21
 
33
22
  # gives us a graceful exit
34
- setup_trap_int
35
-
36
- if @shutdown
37
- EM.next_tick do # change to add_timer(1) for more delay
38
- @run = false
39
- end
40
- end
23
+ setup_interrupt_handling
41
24
 
42
- # allows us to break out of the loop
25
+ # this is the entry to message handling
43
26
  EM.add_periodic_timer do
44
- unless @run
45
- EM.stop unless @run
46
- end
47
- end
48
27
 
49
- # ensures we can continue to run other specs
50
- EM.add_shutdown_hook { puts("destroy"); @ctx.destroy }
28
+ # blocking ZMQ socket
29
+ message = puller.recv || ""
51
30
 
52
- # this is the entry to message handling
53
- EM.add_periodic_timer do
54
- @redis_pool.perform do |conn|
55
- message_handler = MessageHandler.new @puller.recv, conn
56
-
57
- message_handler.callback do |response|
58
- puts response.inspect
59
- end
60
- message_handler.run
61
- message_handler
31
+ # take a worker from the pool to save the metric to Redis
32
+ redis_pool.perform do |conn|
33
+
34
+ message_hash = JSON.parse(message)
35
+ metric_type = message_hash.delete("metric_type")
36
+
37
+ response = conn.rpush "profit:metric:#{metric_type}", message_hash.to_json
38
+ response.callback { |resp| puts "callback: #{resp}"}
39
+ response.errback { |resp| puts "errback: #{resp}"}
40
+ response
62
41
  end
63
42
  end
64
43
  end
65
44
  end
45
+
46
+ private
47
+
48
+ def setup_interrupt_handling
49
+ trap(:INT) { EM.stop }
50
+ EM.add_shutdown_hook { ctx.destroy }
51
+ end
52
+
53
+ def spawn_redis_connections
54
+ spawn = lambda { redis_pool.add(EM::Hiredis.connect(redis_address)) }
55
+ redis_pool.on_error { |conn| spawn[] }
56
+ @options[:pool_size].times { spawn[] }
57
+ end
58
+
59
+ def puller
60
+ @puller ||= ctx.bind(:PULL, @options[:zmq_address])
61
+ end
62
+
63
+ def redis_pool
64
+ @redis_pool ||= EM::Pool.new
65
+ end
66
+
67
+ def redis_address
68
+ "redis://#{@options[:redis_address]}:#{@options[:redis_port]}/"
69
+ end
66
70
  end
67
71
  end
@@ -1,3 +1,3 @@
1
1
  module Profit
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -8,11 +8,11 @@ describe Profit::Client do
8
8
  let!(:server_thread) { TestServer.server_thread }
9
9
 
10
10
  after do
11
- redis.del("some_foo_measurement")
11
+ redis.del("profit:metric:some_foo_measurement")
12
12
  end
13
13
 
14
14
  it "sends the amount of time it takes to run some code" do
15
- metrics = redis.lrange("some_foo_measurement", 0, -1)
15
+ metrics = redis.lrange("profit:metric:some_foo_measurement", 0, -1)
16
16
  expect(metrics).to be_empty
17
17
 
18
18
  client.start("some_foo_measurement")
@@ -21,7 +21,7 @@ describe Profit::Client do
21
21
 
22
22
  server_thread.join(0.1)
23
23
 
24
- metrics = redis.lrange("some_foo_measurement", 0, -1)
24
+ metrics = redis.lrange("profit:metric:some_foo_measurement", 0, -1)
25
25
  metric = JSON.parse(metrics.first)
26
26
  expect(metric['recorded_time']).to be_within(0.1).of(1)
27
27
  end
@@ -80,8 +80,8 @@ describe Profit::Client do
80
80
  describe "#stop" do
81
81
 
82
82
  after do
83
- redis.del("m_1")
84
- redis.del("m_2")
83
+ redis.del("profit:metric:m_1")
84
+ redis.del("profit:metric:m_2")
85
85
  end
86
86
 
87
87
  it "matches up with the start marker" do
@@ -101,8 +101,8 @@ describe Profit::Client do
101
101
 
102
102
  server_thread.join(0.1)
103
103
 
104
- first_measurement_list = redis.lrange("m_1", 0, -1)
105
- second_measurement_list = redis.lrange("m_2", 0, -1)
104
+ first_measurement_list = redis.lrange("profit:metric:m_1", 0, -1)
105
+ second_measurement_list = redis.lrange("profit:metric:m_2", 0, -1)
106
106
 
107
107
  expect(first_measurement_list.count).to eq 2
108
108
  expect(second_measurement_list.count).to eq 1
@@ -121,7 +121,7 @@ describe Profit::Client do
121
121
 
122
122
  server_thread.join(0.1)
123
123
 
124
- measurements = redis.lrange("m_1", 0, -1)
124
+ measurements = redis.lrange("profit:metric:m_1", 0, -1)
125
125
  metric = JSON.parse(measurements[0])
126
126
  expect(metric['stop_file']).to eq stop_file
127
127
  expect(metric['stop_line']).to eq stop_line
@@ -7,7 +7,7 @@ describe Profit::Server do
7
7
  let!(:server_thread) { TestServer.server_thread }
8
8
 
9
9
  after do
10
- redis.del("some_slow_piece_of_code")
10
+ redis.del("profit:metric:some_slow_piece_of_code")
11
11
  end
12
12
 
13
13
  it "stores metrics messages" do
@@ -22,9 +22,9 @@ describe Profit::Server do
22
22
  end_file: "/foo/bar/biz.rb" }.to_json)
23
23
  server_thread.join(0.1)
24
24
 
25
- list = redis.lrange("some_slow_piece_of_code", 0, -1)
25
+ list = redis.lrange("profit:metric:some_slow_piece_of_code", 0, -1)
26
26
  expect(list.count).to eq 1
27
- expect(redis.llen("some_slow_piece_of_code")).to eq 1
27
+ expect(redis.llen("profit:metric:some_slow_piece_of_code")).to eq 1
28
28
 
29
29
  metric = JSON.parse(list[0])
30
30
  expect(metric["total_time"]).to eq 12.012
@@ -1,4 +1,5 @@
1
1
  require './lib/profit'
2
+ require 'redis'
2
3
 
3
4
  class TestServer
4
5
 
@@ -18,7 +19,6 @@ RSpec.configure do |config|
18
19
  end
19
20
 
20
21
  config.after(:suite) do
21
- TestServer.server.shutdown!
22
22
  TestServer.server_thread.join(1)
23
23
  end
24
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: profit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-09 00:00:00.000000000 Z
12
+ date: 2013-06-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -44,7 +44,7 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
46
  - !ruby/object:Gem::Dependency
47
- name: redis
47
+ name: em-hiredis
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
@@ -75,6 +75,22 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: redis
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
78
94
  - !ruby/object:Gem::Dependency
79
95
  name: rspec
80
96
  requirement: !ruby/object:Gem::Requirement
@@ -117,7 +133,6 @@ extensions: []
117
133
  extra_rdoc_files: []
118
134
  files:
119
135
  - lib/profit/client.rb
120
- - lib/profit/message_handler.rb
121
136
  - lib/profit/server.rb
122
137
  - lib/profit/version.rb
123
138
  - lib/profit.rb
@@ -140,7 +155,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
155
  version: '0'
141
156
  segments:
142
157
  - 0
143
- hash: -1338827002242441259
158
+ hash: -1836147071158890398
144
159
  required_rubygems_version: !ruby/object:Gem::Requirement
145
160
  none: false
146
161
  requirements:
@@ -149,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
164
  version: '0'
150
165
  segments:
151
166
  - 0
152
- hash: -1338827002242441259
167
+ hash: -1836147071158890398
153
168
  requirements: []
154
169
  rubyforge_project:
155
170
  rubygems_version: 1.8.23
@@ -1,26 +0,0 @@
1
-
2
- module Profit
3
-
4
- class MessageHandler
5
-
6
- include EM::Deferrable
7
-
8
- attr_reader :text
9
-
10
- def initialize(json, conn)
11
- @json, @conn = json, conn
12
- end
13
-
14
- def run
15
- return succeed("Starting") if @json.empty?
16
- message_hash = JSON.parse(@json)
17
- key = message_hash.delete("metric_type")
18
- response = @conn.rpush key, message_hash.to_json
19
- if response == "OK"
20
- succeed response
21
- else
22
- fail response
23
- end
24
- end
25
- end
26
- end