daikon 0.7.4 → 0.7.5

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.
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{daikon}
8
- s.version = "0.7.4"
8
+ s.version = "0.7.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Nick Quaranto"]
12
- s.date = %q{2011-02-11}
12
+ s.date = %q{2011-02-17}
13
13
  s.default_executable = %q{daikon}
14
14
  s.description = %q{daikon, a radishapp.com client}
15
15
  s.email = %q{nick@quaran.to}
@@ -32,7 +32,6 @@ Gem::Specification.new do |s|
32
32
  "lib/daikon/configuration.rb",
33
33
  "lib/daikon/daemon.rb",
34
34
  "lib/daikon/monitor.rb",
35
- "lib/daikon/namespace_tools.rb",
36
35
  "lib/daikon/redis_hacks.rb",
37
36
  "spec/client_spec.rb",
38
37
  "spec/configuration_spec.rb",
@@ -18,7 +18,6 @@ $LOAD_PATH.unshift __DIR__ unless
18
18
  $LOAD_PATH.include?(__DIR__) ||
19
19
  $LOAD_PATH.include?(File.expand_path(__DIR__))
20
20
 
21
- require 'daikon/namespace_tools'
22
21
  require 'daikon/configuration'
23
22
  require 'daikon/client'
24
23
  require 'daikon/daemon'
@@ -26,5 +25,5 @@ require 'daikon/monitor'
26
25
  require 'daikon/redis_hacks'
27
26
 
28
27
  module Daikon
29
- VERSION = "0.7.4"
28
+ VERSION = "0.7.5"
30
29
  end
@@ -1,7 +1,5 @@
1
1
  module Daikon
2
2
  class Client
3
- include NamespaceTools
4
-
5
3
  EXCEPTIONS = [Timeout::Error,
6
4
  Errno::EINVAL,
7
5
  Errno::ECONNRESET,
@@ -58,21 +56,6 @@ module Daikon
58
56
  "Content-Type" => "application/json"})
59
57
  end
60
58
 
61
- def fetch_commands
62
- raw_commands = request(:get, "/api/v1/commands.json")
63
- commands = JSON.parse(raw_commands.body)
64
-
65
- commands.each do |id, command|
66
- result = evaluate_redis(command)
67
- pretty = StringIO.new
68
- PP.pp(result, pretty)
69
-
70
- push :put, "/api/v1/commands/#{id}.json", {"response" => pretty.string.strip}
71
- end
72
- rescue *EXCEPTIONS => ex
73
- exception(ex)
74
- end
75
-
76
59
  def rotate_monitor(start, stop)
77
60
  payload = monitor.rotate.merge({
78
61
  "start" => start,
@@ -89,41 +72,5 @@ module Daikon
89
72
  rescue *EXCEPTIONS => ex
90
73
  exception(ex)
91
74
  end
92
-
93
- def evaluate_redis(command)
94
- # Attempt to parse the given command string.
95
- argv =
96
- begin
97
- Shellwords.shellwords(command.to_s)
98
- rescue Exception => e
99
- exception(e)
100
- return e.message
101
- end
102
- return "No command received." unless argv[0]
103
-
104
- begin
105
- execute_redis(argv)
106
- rescue Exception => e
107
- exception(e)
108
- e.message
109
- end
110
- end
111
-
112
- def namespace
113
- nil
114
- end
115
-
116
- def execute_redis(argv)
117
- # Apply the current namespace to any fields that need it.
118
- argv = namespace_input(namespace, *argv)
119
-
120
- raise "Not a Redis command." unless argv.kind_of? Array
121
-
122
- # Send the command to Redis.
123
- result = redis.send(*argv)
124
-
125
- # Remove the namespace from any commands that return a key.
126
- denamespace_output namespace, argv.first, result
127
- end
128
75
  end
129
76
  end
@@ -59,6 +59,9 @@ module Daikon
59
59
  def push(raw_command)
60
60
  command, key, *rest = raw_command.strip.gsub('"', '').split
61
61
  command.upcase!
62
+
63
+ return unless ALL_COMMANDS.member?(command)
64
+
62
65
  lock do
63
66
  incr_command(command)
64
67
  incr_total(command)
@@ -85,7 +88,7 @@ module Daikon
85
88
  end
86
89
 
87
90
  def incr_command(command)
88
- data["commands"][command] += 1 if ALL_COMMANDS.member?(command)
91
+ data["commands"][command] += 1
89
92
  end
90
93
 
91
94
  def incr_key(key)
@@ -37,72 +37,6 @@ describe Daikon::Client, "setup" do
37
37
  end
38
38
  end
39
39
 
40
- shared_examples_for "a command api consumer" do
41
- it "sends a request for commands" do
42
- http.should have_received(:request).with(
43
- :method => "GET",
44
- :path => "/api/v1/commands.json",
45
- :headers => {"Authorization" => api_key})
46
- end
47
-
48
- it "processes each command" do
49
- subject.should have_received(:evaluate_redis).with("INCR foo")
50
- subject.should have_received(:evaluate_redis).with("DECR foo")
51
- end
52
-
53
- it "shoots the results back to radish" do
54
- results = {"response" => "9999"}.to_json
55
-
56
- headers = {
57
- "Authorization" => api_key,
58
- "Content-Length" => results.size.to_s,
59
- "Content-Type" => "application/json"
60
- }
61
-
62
- http.should have_received(:request).with(
63
- :method => "PUT",
64
- :path => "/api/v1/commands/42.json",
65
- :body => results,
66
- :headers => headers)
67
-
68
- http.should have_received(:request).with(
69
- :method => "PUT",
70
- :path => "/api/v1/commands/43.json",
71
- :body => results,
72
- :headers => headers)
73
- end
74
- end
75
-
76
- describe Daikon::Client, "fetching commands" do
77
- subject { Daikon::Client.new }
78
- let(:body) { {"42" => "INCR foo", "43" => "DECR foo"}.to_json }
79
- let(:http) { stub("http", :request => Excon::Response.new(:body => body)) }
80
-
81
- before do
82
- subject.stubs(:evaluate_redis => 9999)
83
- subject.stubs(:http => http)
84
-
85
- subject.setup(config)
86
- subject.fetch_commands
87
- end
88
-
89
- context "with default configuration" do
90
- let(:api_key) { config.api_key }
91
- let(:server) { "https://radish.heroku.com" }
92
- let(:config) { Daikon::Configuration.new([]) }
93
-
94
- it_should_behave_like "a command api consumer"
95
- end
96
-
97
- context "with custom settings" do
98
- let(:api_key) { "0987654321" }
99
- let(:server) { "http://localhost:9999" }
100
- let(:config) { Daikon::Configuration.new(["-k", api_key, "-s", "http://localhost:9999"]) }
101
-
102
- it_should_behave_like "a command api consumer"
103
- end
104
- end
105
-
106
40
  describe Daikon::Client, "when server is down" do
107
41
  subject { Daikon::Client.new }
108
42
  before do
@@ -114,7 +48,7 @@ describe Daikon::Client, "when server is down" do
114
48
 
115
49
  it "does not commit suicide" do
116
50
  lambda {
117
- subject.fetch_commands
51
+ subject.report_info
118
52
  }.should_not raise_error
119
53
  end
120
54
  end
@@ -129,7 +63,7 @@ describe Daikon::Client, "when it returns bad json" do
129
63
 
130
64
  it "does not commit suicide" do
131
65
  lambda {
132
- subject.fetch_commands
66
+ subject.report_info
133
67
  }.should_not raise_error
134
68
  end
135
69
  end
@@ -194,27 +128,6 @@ describe Daikon::Client, "rotate monitor" do
194
128
  end
195
129
  end
196
130
 
197
- describe Daikon::Client, "pretty printing results" do
198
- subject { Daikon::Client.new }
199
- let(:body) { {"13" => "LRANGE foo 0 -1"}.to_json }
200
- let(:list) { %w[apples bananas carrots] }
201
- let(:server) { "https://radish.heroku.com" }
202
- let(:config) { Daikon::Configuration.new }
203
- let(:http) { stub("http", :request => Excon::Response.new(:body => body)) }
204
-
205
- before do
206
- subject.stubs(:evaluate_redis => list, :http => http)
207
- subject.setup(config)
208
- subject.fetch_commands
209
- end
210
-
211
- it "returns pretty printed results" do
212
- http.should have_received(:request).with(has_entry(
213
- :body => {"response" => "[\"apples\", \"bananas\", \"carrots\"]"}.to_json
214
- ))
215
- end
216
- end
217
-
218
131
  shared_examples_for "a info api consumer" do
219
132
  it "shoots the results back to radish" do
220
133
  headers = {
@@ -160,3 +160,17 @@ describe Daikon::Monitor, "#rotate that collects namespaces" do
160
160
  data["namespaces"]["s3"].should == 1
161
161
  end
162
162
  end
163
+
164
+ describe Daikon::Monitor, "#rotate with values that have spaces" do
165
+ before do
166
+ subject.parse("set g:2470920:mrn 11")
167
+ subject.parse("Email Error")
168
+ end
169
+
170
+ it "keeps track of namespace accesses" do
171
+ data = subject.rotate
172
+ data["commands"].should == {"SET" => 1}
173
+ data["keys"].should == {"g:2470920:mrn" => 1}
174
+ data["namespaces"].should == {"g" => 1}
175
+ end
176
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 4
9
- version: 0.7.4
8
+ - 5
9
+ version: 0.7.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nick Quaranto
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-02-11 00:00:00 -05:00
17
+ date: 2011-02-17 00:00:00 -05:00
18
18
  default_executable: daikon
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -165,7 +165,6 @@ files:
165
165
  - lib/daikon/configuration.rb
166
166
  - lib/daikon/daemon.rb
167
167
  - lib/daikon/monitor.rb
168
- - lib/daikon/namespace_tools.rb
169
168
  - lib/daikon/redis_hacks.rb
170
169
  - spec/client_spec.rb
171
170
  - spec/configuration_spec.rb
@@ -1,122 +0,0 @@
1
- module Daikon
2
- module NamespaceTools
3
- def namespace_input(ns, command, *args)
4
- command = command.to_s.downcase
5
-
6
- case command
7
-
8
- when "multi", "exec", "discard"
9
-
10
- # No arguments.
11
-
12
- [ command ]
13
-
14
- when "exists", "del", "type", "keys", "ttl", "set", "get", "getset",
15
- "setnx", "incr", "incrby", "decr", "decrby", "rpush", "lpush",
16
- "llen", "lrange", "ltrim", "lindex", "lset", "lrem", "lpop", "rpop",
17
- "sadd", "srem", "spop", "scard", "sismember", "smembers", "srandmember",
18
- "zadd", "zrem", "zincrby", "zrange", "zrevrange", "zrangebyscore",
19
- "zcard", "zscore", "zremrangebyscore", "expire", "expireat", "hlen",
20
- "hkeys", "hvals", "hgetall", "hset", "hget", "hincrby", "hexists",
21
- "hdel", "hmset"
22
-
23
- # Only the first argument is a key.
24
-
25
- head = add_namespace(ns, args.first)
26
- tail = args[1, args.length - 1] || []
27
-
28
- [ command, head, *tail ]
29
-
30
- when "smove"
31
-
32
- # The first two parmeters are keys.
33
-
34
- result = [ command ]
35
-
36
- args.each_with_index do |arg, i|
37
- result << ((i == 0 || i == 1) ? add_namespace(ns, arg) : arg)
38
- end
39
-
40
- result
41
-
42
- when "mget", "rpoplpush", "sinter", "sunion", "sdiff", "info",
43
- "sinterstore", "sunionstore", "sdiffstore", "dbsize"
44
-
45
- # All arguments are keys.
46
-
47
- keys = add_namespace(ns, args)
48
-
49
- [ command, *keys ]
50
-
51
- when "mset", "msetnx"
52
-
53
- # Every other argument is a key, starting with the first.
54
-
55
- hash1 = Hash[*args]
56
- hash2 = {}
57
-
58
- hash1.each do |k, v|
59
- hash2[add_namespace(ns, k)] = hash1.delete(k)
60
- end
61
-
62
- [ command, hash2 ]
63
-
64
- when "sort"
65
-
66
- return [] if args.count == 0
67
-
68
- key = add_namespace(ns, args.shift)
69
- parms = {}
70
-
71
- while keyword = args.shift.andand.downcase
72
- case keyword
73
- when "by", "get", "store"
74
- k = keyword.intern
75
- v = add_namespace(ns, args.shift)
76
-
77
- parms[k] = v
78
- when "limit"
79
- parms[:limit] = [ args.shift.to_i, args.shift.to_i ]
80
- when "asc", "desc", "alpha"
81
- parms[:order].andand << " "
82
- parms[:order] ||= ""
83
- parms[:order] << keyword
84
- end
85
- end
86
-
87
- [ command, key, parms ]
88
-
89
- end
90
- end
91
-
92
- def denamespace_output(namespace, command, result)
93
- case command.to_s.downcase
94
-
95
- when "keys"
96
- remove_namespace namespace, result
97
-
98
- else
99
- result
100
-
101
- end
102
- end
103
-
104
- def add_namespace(namespace, key)
105
- return key unless namespace
106
-
107
- case key
108
- when String then "#{namespace}:#{key}"
109
- when Array then key.map {|k| add_namespace(namespace, k)}
110
- end
111
- end
112
-
113
- def remove_namespace(namespace, key)
114
- return key unless namespace
115
-
116
- case key
117
- when String then key.gsub(/^#{namespace}:/, "")
118
- when Array then key.map {|k| remove_namespace(namespace, k)}
119
- end
120
- end
121
- end
122
- end