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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6559932c80aa96627db70da45c2f911ff3dcdf5c
4
- data.tar.gz: c6dc2f87865ab21682371a16609a239c25c7de2e
3
+ metadata.gz: b5a7bf0e877c516e9c5e5d3ab5592a3f7e2dbea3
4
+ data.tar.gz: 16575e3d5b0a651e0ed801db1769f640d9401f75
5
5
  SHA512:
6
- metadata.gz: 991490a0e2acbe36aa3080a854047a39604e9d4ebec2796a26a365fce95a9c04952728b6f720a69999f3933e74bf2cf8ca3168911484c652b246aedc087e2ac6
7
- data.tar.gz: 086812da4bd01e882a7e7a986c0ed7c305e5a37e66ad6ffa985f59b904aa82eb5ea64e00f2113238ac1ef0192831883676073b24d4f8b361f1739716fd0f71bc
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
- key = [bucket, '/', self.send(using).try(:to_s)].join('')
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
- key = [bucket, '/', self.send(using).try(:to_s)].join('')
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
@@ -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
- entity = entity_id.to_s.gsub('_id', '')
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
@@ -1,3 +1,3 @@
1
1
  module Lookist
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
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.should eq({table: {
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.should eq({table: {
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.should eq({table: {
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.should eq({table: {
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
  }})
@@ -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.3
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