lark 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.markdown +10 -8
  2. data/VERSION +1 -1
  3. data/lib/lark.rb +88 -63
  4. data/spec/lark_spec.rb +9 -8
  5. metadata +3 -3
@@ -3,20 +3,22 @@
3
3
  Lark is a simple system to store local cache in a cluster of redis servers, be
4
4
  able to query state about other lark nodes, and notice when one goes offline.
5
5
 
6
- Lark.on_expire do |id|
6
+ Lark.on_expired do |id|
7
7
  Log.debug "Lost node #{id}"
8
8
  end
9
9
 
10
- EM.start do
11
- lark = Lark.new "bottom_node.1", :expire => 60
12
- lark.set "ip" => "127.0.0.1", "role" => "worker node"
13
- EM::PeriodicTimer(5) do
10
+ Lark.configure :domain => "staging", :expire => 60
11
+
12
+ EM.run do
13
+ lark = Lark::Base.new "bottom_node.1", "group3", "ip" => "127.0.0.1", "role" => "worker node"
14
+
15
+ EM::PeriodicTimer.new(5) do
14
16
  lark.set "load" => get_load, "mem_usage" => get_mem_usage
15
17
  end
16
18
 
17
19
  on_some_event do
18
- lark.find(/^top_node/).each do |id, data|
19
- check_on_node(id, data)
20
- do
20
+ Lark.get(:group3).each do |n|
21
+ check_on_node(n)
22
+ end
21
23
  end
22
24
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -2,11 +2,27 @@ require 'redis'
2
2
 
3
3
  class LarkDBOffline < Exception ; end
4
4
 
5
- class Lark
6
- attr_accessor :id
5
+ module Lark
6
+ # attr_accessor :id
7
7
 
8
- def self.urls
9
- if ENV['LARK_URLS']
8
+ extend self;
9
+
10
+ def configure(options)
11
+ @domain = options[:domain]
12
+ @expire = options[:expire]
13
+ @urls = options[:urls]
14
+ end
15
+
16
+ def domain
17
+ @domain.to_s
18
+ end
19
+
20
+ def urls
21
+ if @urls
22
+ @urls
23
+ elsif @url
24
+ [ @url ]
25
+ elsif ENV['LARK_URLS']
10
26
  ENV['LARK_URLS'].split(",")
11
27
  elsif ENV['LARK_URL']
12
28
  [ ENV['LARK_URL'] ]
@@ -15,20 +31,24 @@ class Lark
15
31
  end
16
32
  end
17
33
 
18
- def self.dbs
34
+ def dbs
19
35
  @dbs ||= urls.map do |url|
20
36
  puts "Connecting to #{url}";
21
37
  Redis.connect(:url => url)
22
38
  end
23
39
  end
24
40
 
41
+ def index(group)
42
+ "#{domain}:#{group}:idx"
43
+ end
44
+
25
45
  ## all the black magic happens here
26
46
  ## pool runs the block against all the db's
27
47
  ## throws an error if non of them are online
28
48
  ## and returns an array of the block results
29
49
  ## from the ones who are online
30
50
 
31
- def self.pool(&blk)
51
+ def pool(&blk)
32
52
  dbs.push dbs.shift
33
53
 
34
54
  num_errors = 0
@@ -48,95 +68,100 @@ class Lark
48
68
  results
49
69
  end
50
70
 
51
- def self.on_expired(&blk)
71
+ def on_expired(&blk)
52
72
  @expired = blk;
53
73
  end
54
74
 
55
- def self.expired
56
- @expired
75
+ def index_search(group)
76
+ pool { |db| db.smembers(index(group)) }.flatten.uniq.sort
57
77
  end
58
78
 
59
- def initialize(_id, options = {})
60
- @id = _id
61
- @options = options
62
- @domain = options[:domain]
63
- @expire = options[:expire]
79
+ def key(id, group)
80
+ "#{domain}:#{group}:key:#{id}"
64
81
  end
65
82
 
66
- def load_data
67
- ## try each db - return when one works without an error
68
- ## throw an error if all are down
83
+ def destroy(id, group)
69
84
  pool do |db|
70
- data = db.hgetall(key)
71
- return data if not data.empty?
85
+ db.multi do
86
+ db.del key(id, group)
87
+ db.srem index(group), id
88
+ end
72
89
  end
73
- {}
90
+ @expired.call(id, group) if @expired
74
91
  end
75
92
 
76
- def key
77
- "#{@domain}:#{@id}"
93
+ def clean(group)
94
+ index_search(group).reject { |i| load_data(i, group) }.each { |i| destroy(i, group) }
78
95
  end
79
96
 
80
- def set_key
81
- "#{@domain}:lark:all"
97
+ def get_all(group)
98
+ index_search(group).map { |i| load_data(i, group) }
82
99
  end
83
100
 
84
- def set(new_data)
85
- data.merge!(new_data)
86
- save_data
101
+ def load_data(id, group)
102
+ key = key(id, group)
103
+ ## try each db - return when one works without an error
104
+ ## throw an error if all are down
105
+ pool do |db|
106
+ data = db.hgetall(key)
107
+ return data if not data.empty?
108
+ end
109
+ nil
87
110
  end
88
111
 
89
- def save_data
90
- data[:created_on] ||= Time.new.to_i
91
- data[:domain] ||= @domain
92
- data[:updated_on] = Time.new.to_i
112
+ def save_data(id, group, data)
113
+ key = key(id,group)
114
+
93
115
  pool do |db|
94
116
  db.multi do
95
117
  db.hmset *[ key, data.to_a ].flatten
96
118
  db.expire key, @expire if @expire
97
- db.sadd set_key, @id
119
+ db.sadd index(group), id
98
120
  end
99
121
  end
100
122
  end
101
123
 
102
- def data
103
- @data ||= load_data
124
+ def get(group)
125
+ get_all(group).select { |i| i }
104
126
  end
105
127
 
106
- def destroy
107
- pool do |db|
108
- db.multi do
109
- db.del key
110
- db.srem set_key, id
111
- end
128
+ class Base
129
+ attr_accessor :id, :group
130
+
131
+ def initialize(_id, _group, _data = nil)
132
+ @id = _id
133
+ @group = _group
134
+ @data = _data
135
+ save_data if @data
112
136
  end
113
- self.class.expired.call(id, @domain);
114
- end
115
137
 
116
- def all_ids
117
- pool { |db| db.smembers(set_key) }.flatten.uniq.sort
118
- end
138
+ def key
139
+ Lark.key(id, group)
140
+ end
119
141
 
120
- def find_ids(match)
121
- all_ids.select { |_id| match.match(_id) }
122
- end
142
+ def set(new_data)
143
+ data.merge!(new_data)
144
+ save_data
145
+ end
123
146
 
124
- def find_valid(match)
125
- all = find_ids(match).map { |_id| Lark.new(_id, @options) }
126
- valid = all.reject { |l| l.data.empty? }
127
- invalid = all - valid
128
- invalid.each { |i| i.destroy }
129
- valid
130
- end
147
+ def save_data
148
+ data[:created_on] ||= Time.new.to_i
149
+ data[:updated_on] = Time.new.to_i
150
+ data[:id] = id
151
+ Lark.save_data(id, group, data)
152
+ end
131
153
 
132
- def find(match = //)
133
- result = {}
134
- find_valid(match).each { |v| result[v.id] = v.data }
135
- result
136
- end
154
+ def data
155
+ @data ||= (Lark.load_data(key) || {})
156
+ end
137
157
 
138
- def pool(&blk)
139
- self.class.pool(&blk)
140
- end
158
+ def destroy
159
+ Lark.destroy(id, group)
160
+ end
141
161
 
162
+ def pool(&blk)
163
+ self.class.pool(&blk)
164
+ end
165
+
166
+ end
142
167
  end
@@ -2,26 +2,27 @@
2
2
  require File.dirname(__FILE__) + "/init.rb"
3
3
 
4
4
  describe 'Lark' do
5
+
5
6
  before do
6
- @lark = Lark.new "lark", :domain => "domain"
7
- @db1 = mock()
8
- @db2 = mock()
7
+ @group = :testgroup
8
+ @db1 = mock()
9
+ @db2 = mock()
9
10
  Lark.stubs(:dbs).returns([@db1, @db2]);
10
11
  end
11
12
 
12
13
  it 'should locate the data even if the key and data are on different databases' do
13
- @db1.expects(:smembers).returns([ "key1" ])
14
- @db1.expects(:hgetall).with("domain:key1").returns({})
14
+ @db1.expects(:smembers).returns([ "test123" ])
15
+ @db1.expects(:hgetall).with(":#{@group}:key:test123").returns({})
15
16
  @db2.expects(:smembers).returns([ ])
16
- @db2.expects(:hgetall).with("domain:key1").returns({"foo" => "bar"})
17
+ @db2.expects(:hgetall).with(":#{@group}:key:test123").returns({"foo" => "bar"})
17
18
 
18
- @lark.find.should.equal({ "key1" => {"foo" => "bar"} })
19
+ Lark.get(@group).should.equal([ {"foo" => "bar"} ])
19
20
  end
20
21
 
21
22
  it 'should get the union of the ids on each server' do
22
23
  @db1.expects(:smembers).returns([ "a", "b" ])
23
24
  @db2.expects(:smembers).returns([ "b", "c" ])
24
- @lark.all_ids.should.equal ["a","b","c"]
25
+ Lark.index_search(@group).should.equal ["a","b","c"]
25
26
  end
26
27
 
27
28
  # it 'should run delete on old objects'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lark
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Orion Henry