couch_potato 1.15.0 → 1.17.0

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
  SHA256:
3
- metadata.gz: ffcaae6b2815d237b48cc3e4ad553f66920fe4df2c84c59ae38177260949ba6b
4
- data.tar.gz: bd266a1033fa83fcba822a19e3de86b2c1aac2d80ba2dd1d3aef0920d4819d8f
3
+ metadata.gz: a78d19f65a75932bb6f60639fc9ad3dff0151e9c7de7f8cbc31e1b61038f7fa8
4
+ data.tar.gz: c5383ffd3db50bd45d727a84b62588dcd70d6ea3d07ac96559e1318c145fb057
5
5
  SHA512:
6
- metadata.gz: 16f3e1748e3b3314f1cf3d658fb175dd90c5e7c7cd717ab42477961c364bac527b262642a29f208c4aad200e9a31ce7470c0a538db8bf8d641e13da92f85debb
7
- data.tar.gz: '089f1c9e5dc7238b659a4d1b2d0f3d341a084fe52f6d9c2d058ea8440f197f7d64b6f5a9d78c8cebbd19b131aede038329ab6c0f79b503d220f1f20d2e7d8a20'
6
+ metadata.gz: 38aa7ce10b0f12429789ecc0f25e34b276f98eadedac900f2ea18b7c1845549be28becb624d4da1c89506d814fa403b7f9647f960f3be534ac47b02c839f6866
7
+ data.tar.gz: e0b48a96f9a485d0765b066b5e5bca043058b85af246775abdf2bf3afb598bf691b09ae156182b9ecf1ff9dcc0acdee3bb5cc899a8722d0a75bdff9ded965b7b
data/CHANGES.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## Changes
2
2
 
3
+ # 1.17.0
4
+
5
+ - filter out nil ids for loading multiple documents
6
+ - cache nil documents
7
+
8
+ # 1.16.0
9
+
10
+ - add payload to ActiveSupport instrumentation calls
11
+ - only notify load.cached when there are cached documents
12
+
3
13
  # 1.15.0
4
14
 
5
15
  - cache loading multiple documents
@@ -149,8 +149,8 @@ module CouchPotato
149
149
 
150
150
  cached = cache && cache[id]
151
151
  if cache
152
- if cached
153
- ActiveSupport::Notifications.instrument('couch_potato.load.cached') do
152
+ if cache.key?(id)
153
+ ActiveSupport::Notifications.instrument('couch_potato.load.cached', id: id, doc: cached) do
154
154
  cached
155
155
  end
156
156
  else
@@ -164,19 +164,23 @@ module CouchPotato
164
164
  alias load load_document
165
165
 
166
166
  def load_documents(ids)
167
+ ids = ids.compact
167
168
  return [] if ids.empty?
168
169
 
169
170
  uncached_ids = ids - (cache&.keys || [])
170
171
  uncached_docs_by_id = bulk_load(uncached_ids).index_by {|doc| doc.id if doc.respond_to?(:id) }
172
+ cached_docs_by_id = cache&.slice(*ids) || {}
173
+ if cached_docs_by_id.any?
174
+ ActiveSupport::Notifications.instrument('couch_potato.load.cached', ids: cached_docs_by_id.keys, docs: cached_docs_by_id.values) do
175
+ cached_docs_by_id
176
+ end
177
+ end
171
178
  if cache
172
179
  uncached_ids.each do |id|
173
180
  doc = uncached_docs_by_id[id]
174
- cache[id] = doc if doc
181
+ cache[id] = doc
175
182
  end
176
183
  end
177
- cached_docs_by_id = ActiveSupport::Notifications.instrument('couch_potato.load.cached') do
178
- cache&.slice(*ids) || {}
179
- end
180
184
  ids.filter_map { |id| (cached_docs_by_id[id]) || uncached_docs_by_id[id] }
181
185
  end
182
186
 
@@ -278,9 +282,11 @@ module CouchPotato
278
282
  def load_document_without_caching(id)
279
283
  raise "Can't load a document without an id (got nil)" if id.nil?
280
284
 
281
- ActiveSupport::Notifications.instrument('couch_potato.load') do
285
+ payload = {id: id}
286
+ ActiveSupport::Notifications.instrument('couch_potato.load', payload) do
282
287
  instance = couchrest_database.get(id)
283
288
  instance.database = self if instance
289
+ payload[:doc] = instance
284
290
  instance
285
291
  end
286
292
  end
@@ -321,9 +327,11 @@ module CouchPotato
321
327
  def bulk_load(ids)
322
328
  return [] if ids.empty?
323
329
 
324
- ActiveSupport::Notifications.instrument('couch_potato.load') do
330
+ payload = {ids: ids}
331
+ ActiveSupport::Notifications.instrument('couch_potato.load', payload) do
325
332
  response = couchrest_database.bulk_load ids
326
- docs = response['rows'].map { |row| row['doc'] }.compact
333
+ docs = response["rows"].map { |row| row["doc"] }.compact
334
+ payload[:docs] = docs
327
335
  docs.each do |doc|
328
336
  doc.database = self if doc.respond_to?(:database=)
329
337
  doc.database_collection = docs if doc.respond_to?(:database_collection=)
@@ -1,12 +1,16 @@
1
1
  module CouchPotato
2
- module GhostAttributes #:nodoc:
3
- def method_missing(name, *args)
4
- if(value = _document && _document[name.to_s])
2
+ module GhostAttributes # :nodoc:
3
+ def method_missing(name, *)
4
+ if (value = _document && _document[name.to_s])
5
5
  value
6
6
  else
7
7
  super
8
8
  end
9
9
  end
10
+
11
+ def respond_to_missing?(name, *)
12
+ _document && _document[name.to_s]
13
+ end
10
14
  end
11
15
  end
12
16
 
@@ -1,4 +1,4 @@
1
1
  module CouchPotato
2
- VERSION = '1.15.0'.freeze
2
+ VERSION = '1.17.0'.freeze
3
3
  RSPEC_VERSION = '4.1.0'.freeze
4
4
  end
@@ -18,6 +18,10 @@ RSpec.describe 'database caching' do
18
18
  {}
19
19
  end
20
20
 
21
+ after(:each) do
22
+ ActiveSupport::Notifications.unsubscribe(@subscriber) if @subscriber
23
+ end
24
+
21
25
  context 'for a single document' do
22
26
  it 'gets an object from the cache the 2nd time via #load_documemt' do
23
27
  expect(couchrest_db).to receive(:get).with('1').exactly(1).times
@@ -33,6 +37,15 @@ RSpec.describe 'database caching' do
33
37
  db.load '1'
34
38
  end
35
39
 
40
+ it 'caches nil' do
41
+ allow(couchrest_db).to receive(:get).with('1').and_return(nil)
42
+
43
+ db.load '1'
44
+ db.load '1'
45
+
46
+ expect(couchrest_db).to have_received(:get).with('1').exactly(1).times
47
+ end
48
+
36
49
  it 'gets an object from the cache the 2nd time via #load!' do
37
50
  expect(couchrest_db).to receive(:get).with('1').exactly(1).times
38
51
 
@@ -47,6 +60,29 @@ RSpec.describe 'database caching' do
47
60
  db.load_document '1'
48
61
  expect(db.load_document('1')).to eql(doc)
49
62
  end
63
+
64
+ it 'instruments the load call' do
65
+ doc = double("doc").as_null_object
66
+ allow(couchrest_db).to receive(:get).and_return(doc)
67
+ events = []
68
+ @subscriber = ActiveSupport::Notifications.subscribe(
69
+ 'couch_potato.load.cached'
70
+ ) do |event|
71
+ events << event
72
+ end
73
+
74
+ db.load("1")
75
+ db.load("1")
76
+
77
+ expect(events.size).to eq(1)
78
+ expect(events.first.payload).to eq(
79
+ {
80
+ id: "1",
81
+ doc: doc
82
+ }
83
+ )
84
+
85
+ end
50
86
  end
51
87
 
52
88
  context 'for multiple documents' do
@@ -65,6 +101,42 @@ RSpec.describe 'database caching' do
65
101
  expect(couchrest_db).to have_received(:bulk_load).with(['2']).exactly(1).times
66
102
  end
67
103
 
104
+ it 'caches nil' do
105
+ allow(couchrest_db).to receive(:bulk_load).with(['1']).and_return('rows' => [{'doc' => nil}])
106
+ allow(couchrest_db).to receive(:bulk_load).with(['2']).and_return('rows' => [{'doc' => doc2}])
107
+
108
+
109
+ db.load_document(['1'])
110
+ db.load_document(['1', '2'])
111
+
112
+ expect(couchrest_db).to have_received(:bulk_load).with(['1']).exactly(1).times
113
+ end
114
+
115
+ it 'instruments the load call' do
116
+ allow(couchrest_db).to receive(:bulk_load).with(['1'])
117
+ .and_return('rows' => [{'doc' => doc1}])
118
+ allow(couchrest_db).to receive(:bulk_load).with(['2'])
119
+ .and_return('rows' => [{'doc' => doc2}])
120
+ events = []
121
+ @subscriber = ActiveSupport::Notifications.subscribe(
122
+ 'couch_potato.load.cached'
123
+ ) do |event|
124
+ events << event
125
+ end
126
+
127
+
128
+ db.load_document(['1'])
129
+ db.load_document(['1', '2'])
130
+
131
+ expect(events.size).to eq(1)
132
+ expect(events.first.payload).to eq(
133
+ {
134
+ ids: ["1"],
135
+ docs: [doc1]
136
+ }
137
+ )
138
+ end
139
+
68
140
  it 'loads nothing if all documents are cached' do
69
141
  allow(couchrest_db).to receive(:bulk_load).with(['1', '2'])
70
142
  .and_return('rows' => [{'doc' => doc1}, {'doc' => doc2}])
@@ -85,22 +157,6 @@ RSpec.describe 'database caching' do
85
157
 
86
158
  expect(result).to eql([doc1, doc2])
87
159
  end
88
-
89
- it 'does not cache documents that do not respond to id' do
90
- doc1 = {
91
- 'id' => '1',
92
- }
93
- doc2 = {
94
- 'id' => '2',
95
- }
96
- allow(couchrest_db).to receive(:bulk_load).with(['1', '2'])
97
- .and_return('rows' => [{'doc' => doc1}, {'doc' => doc1}])
98
-
99
- db.load_document(['1', '2'])
100
- db.load_document(['1', '2'])
101
-
102
- expect(couchrest_db).to have_received(:bulk_load).with(['1', '2']).exactly(2).times
103
- end
104
160
  end
105
161
 
106
162
  context 'when switching the database' do
@@ -42,6 +42,11 @@ describe CouchPotato::Database, 'load' do
42
42
  let(:couchrest_db) { double('couchrest db', info: nil).as_null_object }
43
43
  let(:db) { CouchPotato::Database.new couchrest_db }
44
44
 
45
+
46
+ after(:each) do
47
+ ActiveSupport::Notifications.unsubscribe(@subscriber) if @subscriber
48
+ end
49
+
45
50
  it 'should raise an exception if nil given' do
46
51
  expect do
47
52
  db.load nil
@@ -87,6 +92,12 @@ describe CouchPotato::Database, 'load' do
87
92
  db.load %w[1 2 3]
88
93
  end
89
94
 
95
+ it 'does not request anything when nil is given' do
96
+ expect(db.load([nil])).to eq([])
97
+
98
+ expect(couchrest_db).not_to have_received(:bulk_load)
99
+ end
100
+
90
101
  it 'returns only found documents' do
91
102
  expect(db.load(%w[1 2 3]).size).to eq(2)
92
103
  end
@@ -130,6 +141,46 @@ describe CouchPotato::Database, 'load' do
130
141
  it 'returns an empty array when passing an empty array' do
131
142
  expect(db.load([])).to eq([])
132
143
  end
144
+
145
+ it 'instruments the load call' do
146
+ events = []
147
+ @subscriber = ActiveSupport::Notifications.subscribe(
148
+ 'couch_potato.load'
149
+ ) do |event|
150
+ events << event
151
+ end
152
+
153
+ db.load(["1", "2"])
154
+
155
+ expect(events.size).to eq(1)
156
+ expect(events.first.payload).to eq(
157
+ {
158
+ ids: ["1", "2"],
159
+ docs: [doc1, doc2]
160
+ }
161
+ )
162
+ end
163
+ end
164
+
165
+ it 'instruments the load call' do
166
+ doc = double("doc").as_null_object
167
+ allow(couchrest_db).to receive(:get).and_return(doc)
168
+ events = []
169
+ @subscriber = ActiveSupport::Notifications.subscribe(
170
+ 'couch_potato.load'
171
+ ) do |event|
172
+ events << event
173
+ end
174
+
175
+ db.load("1")
176
+
177
+ expect(events.size).to eq(1)
178
+ expect(events.first.payload).to eq(
179
+ {
180
+ id: "1",
181
+ doc: doc
182
+ }
183
+ )
133
184
  end
134
185
  end
135
186
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couch_potato
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.15.0
4
+ version: 1.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Lang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-28 00:00:00.000000000 Z
11
+ date: 2024-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel