looksist 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/lib/looksist.rb +29 -13
- data/lib/looksist/hashed.rb +1 -3
- data/lib/looksist/her_collection.rb +13 -0
- data/lib/looksist/version.rb +1 -1
- data/spec/hashed_spec.rb +5 -4
- data/spec/looksist_spec.rb +58 -0
- data/spec/redis_service_spec.rb +55 -0
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5a7bf0e877c516e9c5e5d3ab5592a3f7e2dbea3
|
4
|
+
data.tar.gz: 16575e3d5b0a651e0ed801db1769f640d9401f75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5efb4ef3b7c9ce4d39c35b1e91d8ff61bb95b270fcb4582bb73f0df9d0388c317890086b0215aa9307127286ae16ff6e2080a15e0469b748712804d82eaf11d2
|
7
|
+
data.tar.gz: ac6029d274ab7e31148abded157c583e39c6486c10dc7f53eed148e604c2497b501f756805bac912ecb394256a9daa704b523c8bdce804bb09d6d9d03ddb44a8
|
data/lib/looksist.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'looksist/version'
|
2
2
|
require 'looksist/redis_service'
|
3
3
|
require 'looksist/hashed'
|
4
|
+
require 'looksist/her_collection'
|
4
5
|
|
5
6
|
module Looksist
|
6
7
|
extend ActiveSupport::Concern
|
@@ -15,32 +16,54 @@ module Looksist
|
|
15
16
|
entity.pluralize
|
16
17
|
end
|
17
18
|
|
19
|
+
def memoized(key)
|
20
|
+
self.storage ||= OpenStruct.new
|
21
|
+
self.storage[key] = self.storage[key] || Looksist.lookup_store_client.get(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def mmemoized(key, values)
|
25
|
+
key_and_bucket = id_and_buckets.find{|h| h[:id] == key}
|
26
|
+
return if key_and_bucket.nil?
|
27
|
+
redis_keys = values.collect{|v| redis_key(key_and_bucket[:bucket], v)}
|
28
|
+
left_keys_to_lookup = redis_keys.select{|k| self.storage[k].nil?}
|
29
|
+
Looksist.lookup_store_client.mapped_mget(left_keys_to_lookup).each do |key, value|
|
30
|
+
self.storage[key] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def redis_key bucket, value
|
36
|
+
[bucket, '/', value].join('')
|
37
|
+
end
|
38
|
+
|
18
39
|
def lookup(what, using, bucket = bucket_name(using))
|
19
40
|
self.lookup_attributes ||= []
|
41
|
+
self.id_and_buckets ||= []
|
42
|
+
self.id_and_buckets << {id: using, bucket: bucket}
|
20
43
|
if what.is_a? Array
|
21
44
|
what.each do |method_name|
|
22
45
|
define_method(method_name) do
|
23
|
-
|
24
|
-
JSON.parse(send(:memoized, key) || '{}')[method_name.to_s]
|
46
|
+
JSON.parse(self.class.memoized(self.class.redis_key(bucket, self.send(using).try(:to_s))) || '{}')[method_name.to_s]
|
25
47
|
end
|
26
48
|
self.lookup_attributes << method_name
|
27
49
|
end
|
28
50
|
else
|
29
51
|
define_method(what) do
|
30
|
-
|
31
|
-
send(:memoized, key)
|
52
|
+
self.class.memoized(self.class.redis_key(bucket, self.send(using).try(:to_s)))
|
32
53
|
end
|
33
54
|
self.lookup_attributes << what.to_sym
|
34
55
|
end
|
35
56
|
end
|
36
57
|
end
|
37
58
|
|
59
|
+
|
60
|
+
|
38
61
|
def as_json(opts)
|
39
62
|
Looksist.driver.json_opts(self, opts)
|
40
63
|
end
|
41
64
|
|
42
65
|
included do |base|
|
43
|
-
base.class_attribute :lookup_attributes
|
66
|
+
base.class_attribute :lookup_attributes, :storage, :id_and_buckets
|
44
67
|
end
|
45
68
|
|
46
69
|
module Serializers
|
@@ -53,11 +76,4 @@ module Looksist
|
|
53
76
|
end
|
54
77
|
end
|
55
78
|
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def memoized(key)
|
60
|
-
@storage = @storage || OpenStruct.new
|
61
|
-
@storage[key] = @storage[key] || Looksist.lookup_store_client.get(key)
|
62
|
-
end
|
63
|
-
end
|
79
|
+
end
|
data/lib/looksist/hashed.rb
CHANGED
@@ -2,8 +2,6 @@ module Looksist
|
|
2
2
|
module Hashed
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
# inject after: :assortment, at: 'table', using: :supplier_id, populate: :supplier_name, bucket_name: 'suppliers'
|
6
|
-
|
7
5
|
class << self;
|
8
6
|
attr_accessor :redis_service
|
9
7
|
end
|
@@ -37,7 +35,7 @@ module Looksist
|
|
37
35
|
end
|
38
36
|
|
39
37
|
def entity(entity_id)
|
40
|
-
|
38
|
+
entity_id.to_s.gsub('_id', '')
|
41
39
|
end
|
42
40
|
end
|
43
41
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Her
|
2
|
+
class Collection
|
3
|
+
def load_all_meta
|
4
|
+
klass = a.first.class
|
5
|
+
return unless klass.respond_to?(:id_and_buckets)
|
6
|
+
id_attributes = klass.id_and_buckets.collect{|h| h[:id]}
|
7
|
+
id_attributes.each do |attribute|
|
8
|
+
id_attribute_values = self.collect(&attribute.to_sym)
|
9
|
+
klass.mmemoized(attribute, id_attribute_values)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/looksist/version.rb
CHANGED
data/spec/hashed_spec.rb
CHANGED
@@ -9,6 +9,7 @@ describe Looksist::Hashed do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
@mock = MockRedis.new
|
12
|
+
|
12
13
|
Looksist::Hashed.redis_service = Looksist::RedisService.instance do |lookup|
|
13
14
|
lookup.client = @mock
|
14
15
|
end
|
@@ -34,7 +35,7 @@ describe Looksist::Hashed do
|
|
34
35
|
expect(@mock).to receive(:get).with('employees/1').and_return(OpenStruct.new(value:'emp 1'))
|
35
36
|
expect(@mock).to receive(:get).with('employees/2').and_return(OpenStruct.new(value:'emp 2'))
|
36
37
|
|
37
|
-
HashService1.new.metrics.
|
38
|
+
expect(HashService1.new.metrics).to eq({table: {
|
38
39
|
employee_id: [1, 2],
|
39
40
|
employee_name: ['emp 1', 'emp 2']
|
40
41
|
}})
|
@@ -63,7 +64,7 @@ describe Looksist::Hashed do
|
|
63
64
|
expect(@mock).to receive(:get).with('employers/3').and_return(OpenStruct.new(value:'empr 3'))
|
64
65
|
expect(@mock).to receive(:get).with('employers/4').and_return(OpenStruct.new(value:'empr 4'))
|
65
66
|
|
66
|
-
HashService.new.metrics.
|
67
|
+
expect(HashService.new.metrics).to eq({table: {
|
67
68
|
employee_id: [5, 6],
|
68
69
|
employer_id: [3, 4],
|
69
70
|
employee_name: ['emp 5', 'emp 6'],
|
@@ -105,12 +106,12 @@ describe Looksist::Hashed do
|
|
105
106
|
expect(@mock).to receive(:get).with('dcs/8').and_return(OpenStruct.new(value:'dc 8'))
|
106
107
|
|
107
108
|
hash_service_super = HashServiceSuper.new
|
108
|
-
hash_service_super.shrinkage.
|
109
|
+
expect(hash_service_super.shrinkage).to eq({table: {
|
109
110
|
shrink_id: [1, 2],
|
110
111
|
shrink_name: ['shrink 1', 'shrink 2']
|
111
112
|
}})
|
112
113
|
|
113
|
-
hash_service_super.stock.
|
114
|
+
expect(hash_service_super.stock).to eq({table: {
|
114
115
|
dc_id: [7, 8],
|
115
116
|
dc_name: ['dc 7', 'dc 8']
|
116
117
|
}})
|
data/spec/looksist_spec.rb
CHANGED
@@ -116,4 +116,62 @@ describe Looksist do
|
|
116
116
|
expect(e.sex).to be(nil)
|
117
117
|
end
|
118
118
|
end
|
119
|
+
|
120
|
+
context 'share storage between instances' do
|
121
|
+
class Employee
|
122
|
+
include Looksist
|
123
|
+
attr_accessor :id
|
124
|
+
|
125
|
+
lookup [:name, :location], using=:id
|
126
|
+
|
127
|
+
def initialize(id)
|
128
|
+
@id = id
|
129
|
+
end
|
130
|
+
end
|
131
|
+
it 'should share storage between instances to improve performance' do
|
132
|
+
employee_first_instance = Employee.new(1)
|
133
|
+
expect(Looksist.lookup_store_client).to receive(:get).with('ids/1')
|
134
|
+
.and_return({name: 'Employee Name', location: 'Chennai'}.to_json)
|
135
|
+
employee_first_instance.name
|
136
|
+
|
137
|
+
employee_second_instance = Employee.new(1)
|
138
|
+
expect(Looksist.lookup_store_client).not_to receive(:get).with('ids/1')
|
139
|
+
|
140
|
+
employee_second_instance.name
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context '.id_and_buckets' do
|
145
|
+
class Developer
|
146
|
+
include Looksist
|
147
|
+
lookup [:city], using=:city_id
|
148
|
+
lookup [:role], using=:role_id
|
149
|
+
end
|
150
|
+
it 'should hold all the id and buckets' do
|
151
|
+
expect(Developer.id_and_buckets).to eq([{id: :city_id, bucket: 'cities'}, {id: :role_id, bucket: 'roles'}])
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context '.mmemoized' do
|
156
|
+
class AnotherDeveloperClass
|
157
|
+
include Looksist
|
158
|
+
lookup [:city], using=:city_id
|
159
|
+
lookup [:role], using=:role_id
|
160
|
+
end
|
161
|
+
|
162
|
+
AnotherDeveloperClass.storage = OpenStruct.new
|
163
|
+
AnotherDeveloperClass.storage['cities/1'] = 'Chennai'
|
164
|
+
AnotherDeveloperClass.storage['cities/2'] = 'Delhi'
|
165
|
+
|
166
|
+
it 'make single request for multiple values' do
|
167
|
+
expect(Looksist.lookup_store_client).to receive(:mapped_mget).with(%w(cities/4 cities/5))
|
168
|
+
.and_return({'cities/4' => 'Bangalore', 'cities/5' => 'Kolkata'})
|
169
|
+
AnotherDeveloperClass.mmemoized(:city_id, [1, 4, 5])
|
170
|
+
|
171
|
+
expect(AnotherDeveloperClass.storage.to_h.length).to eq(4)
|
172
|
+
expect(AnotherDeveloperClass.storage['cities/5']).to eq('Kolkata')
|
173
|
+
expect(AnotherDeveloperClass.storage['cities/4']).to eq('Bangalore')
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
119
177
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Looksist::RedisService do
|
4
|
+
|
5
|
+
class MockRedis
|
6
|
+
def pipelined
|
7
|
+
yield
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'single lookup' do
|
12
|
+
before(:each) do
|
13
|
+
@lookup = Looksist::RedisService.instance do |lookup|
|
14
|
+
lookup.client = {}
|
15
|
+
lookup.buffer_size = 1
|
16
|
+
end
|
17
|
+
@lookup.cache.clear
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should call redis when key not present in cache' do
|
21
|
+
expect(@lookup.client).to receive(:get).with('sub_categories/8001').and_return('CEREALI')
|
22
|
+
expect(@lookup.sub_category_for(8001)).to eq('CEREALI')
|
23
|
+
expect(@lookup.sub_category_for(8001)).to eq('CEREALI')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should abandon older entries incase of buffer overflow' do
|
27
|
+
expect(@lookup.client).to receive(:get).with('sub_families/12').and_return('DON CORLEONE')
|
28
|
+
expect(@lookup.client).to receive(:get).with('sub_families/34').and_return('SOPRANOS')
|
29
|
+
|
30
|
+
expect(@lookup.sub_family_for(12)).to eq('DON CORLEONE')
|
31
|
+
expect(@lookup.sub_family_for(34)).to eq('SOPRANOS')
|
32
|
+
expect(@lookup.cache.keys).to match_array(['sub_families/34'])
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'multi lookup' do
|
38
|
+
|
39
|
+
before(:each) do
|
40
|
+
@mock = MockRedis.new
|
41
|
+
@lookup = Looksist::RedisService.instance do |lookup|
|
42
|
+
lookup.client = @mock
|
43
|
+
lookup.buffer_size = 5
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should pipeline calls to redis when there are multiple keys' do
|
48
|
+
expect(@mock).to receive(:get).with('snacks/1').and_return(OpenStruct.new(value:'BAJJI'))
|
49
|
+
expect(@mock).to receive(:get).with('snacks/2').and_return(OpenStruct.new(value:'BONDA'))
|
50
|
+
expect(@mock).to receive(:get).with('snacks/3').and_return(OpenStruct.new(value:'VADA'))
|
51
|
+
|
52
|
+
expect(@lookup.snacks_for([1,2,3,1])).to match_array(%w(BAJJI BONDA VADA BAJJI))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: looksist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RC
|
@@ -156,11 +156,13 @@ files:
|
|
156
156
|
- Rakefile
|
157
157
|
- lib/looksist.rb
|
158
158
|
- lib/looksist/hashed.rb
|
159
|
+
- lib/looksist/her_collection.rb
|
159
160
|
- lib/looksist/redis_service.rb
|
160
161
|
- lib/looksist/version.rb
|
161
162
|
- looksist.gemspec
|
162
163
|
- spec/hashed_spec.rb
|
163
164
|
- spec/looksist_spec.rb
|
165
|
+
- spec/redis_service_spec.rb
|
164
166
|
- spec/spec_helper.rb
|
165
167
|
homepage: https://github.com/jpsimonroy/herdis
|
166
168
|
licenses:
|
@@ -189,4 +191,5 @@ summary: Redis backed lookup for your her models
|
|
189
191
|
test_files:
|
190
192
|
- spec/hashed_spec.rb
|
191
193
|
- spec/looksist_spec.rb
|
194
|
+
- spec/redis_service_spec.rb
|
192
195
|
- spec/spec_helper.rb
|