lark 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +10 -8
- data/VERSION +1 -1
- data/lib/lark.rb +88 -63
- data/spec/lark_spec.rb +9 -8
- metadata +3 -3
data/README.markdown
CHANGED
@@ -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.
|
6
|
+
Lark.on_expired do |id|
|
7
7
|
Log.debug "Lost node #{id}"
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
19
|
-
check_on_node(
|
20
|
-
|
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
|
+
0.0.2
|
data/lib/lark.rb
CHANGED
@@ -2,11 +2,27 @@ require 'redis'
|
|
2
2
|
|
3
3
|
class LarkDBOffline < Exception ; end
|
4
4
|
|
5
|
-
|
6
|
-
attr_accessor :id
|
5
|
+
module Lark
|
6
|
+
# attr_accessor :id
|
7
7
|
|
8
|
-
|
9
|
-
|
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
|
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
|
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
|
71
|
+
def on_expired(&blk)
|
52
72
|
@expired = blk;
|
53
73
|
end
|
54
74
|
|
55
|
-
def
|
56
|
-
|
75
|
+
def index_search(group)
|
76
|
+
pool { |db| db.smembers(index(group)) }.flatten.uniq.sort
|
57
77
|
end
|
58
78
|
|
59
|
-
def
|
60
|
-
|
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
|
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
|
-
|
71
|
-
|
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
|
77
|
-
|
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
|
81
|
-
|
97
|
+
def get_all(group)
|
98
|
+
index_search(group).map { |i| load_data(i, group) }
|
82
99
|
end
|
83
100
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
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
|
-
|
91
|
-
|
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
|
119
|
+
db.sadd index(group), id
|
98
120
|
end
|
99
121
|
end
|
100
122
|
end
|
101
123
|
|
102
|
-
def
|
103
|
-
|
124
|
+
def get(group)
|
125
|
+
get_all(group).select { |i| i }
|
104
126
|
end
|
105
127
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
138
|
+
def key
|
139
|
+
Lark.key(id, group)
|
140
|
+
end
|
119
141
|
|
120
|
-
|
121
|
-
|
122
|
-
|
142
|
+
def set(new_data)
|
143
|
+
data.merge!(new_data)
|
144
|
+
save_data
|
145
|
+
end
|
123
146
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
133
|
-
|
134
|
-
|
135
|
-
result
|
136
|
-
end
|
154
|
+
def data
|
155
|
+
@data ||= (Lark.load_data(key) || {})
|
156
|
+
end
|
137
157
|
|
138
|
-
|
139
|
-
|
140
|
-
|
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
|
data/spec/lark_spec.rb
CHANGED
@@ -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
|
-
@
|
7
|
-
@db1
|
8
|
-
@db2
|
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([ "
|
14
|
-
@db1.expects(:hgetall).with("
|
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("
|
17
|
+
@db2.expects(:hgetall).with(":#{@group}:key:test123").returns({"foo" => "bar"})
|
17
18
|
|
18
|
-
@
|
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
|
-
@
|
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:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Orion Henry
|