profit 0.1.1 → 0.1.2

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/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