second_level_cache 2.5.2 → 2.6.3
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/CHANGELOG.md +24 -0
- data/README.md +1 -1
- data/lib/second_level_cache.rb +1 -0
- data/lib/second_level_cache/active_record.rb +8 -2
- data/lib/second_level_cache/active_record/base.rb +1 -5
- data/lib/second_level_cache/active_record/belongs_to_association.rb +6 -4
- data/lib/second_level_cache/active_record/fetch_by_uniq_key.rb +24 -17
- data/lib/second_level_cache/active_record/finder_methods.rb +44 -42
- data/lib/second_level_cache/active_record/has_one_association.rb +14 -20
- data/lib/second_level_cache/active_record/preloader.rb +34 -28
- data/lib/second_level_cache/adapter/paranoia.rb +24 -0
- data/lib/second_level_cache/config.rb +1 -0
- data/lib/second_level_cache/log_subscriber.rb +15 -0
- data/lib/second_level_cache/mixin.rb +0 -12
- data/lib/second_level_cache/record_marshal.rb +7 -40
- data/lib/second_level_cache/version.rb +1 -1
- data/second_level_cache.gemspec +23 -22
- data/test/active_record_test_case_helper.rb +11 -1
- data/test/fetch_by_uniq_key_test.rb +47 -4
- data/test/finder_methods_test.rb +39 -0
- data/test/has_one_association_test.rb +16 -4
- data/test/model/account.rb +2 -2
- data/test/model/animal.rb +1 -1
- data/test/model/application_record.rb +3 -0
- data/test/model/book.rb +6 -1
- data/test/model/contribution.rb +14 -0
- data/test/model/image.rb +1 -1
- data/test/model/order.rb +1 -1
- data/test/model/order_item.rb +1 -1
- data/test/model/paranoid.rb +10 -0
- data/test/model/post.rb +1 -1
- data/test/model/topic.rb +1 -1
- data/test/model/user.rb +7 -7
- data/test/paranoid_test.rb +18 -0
- data/test/{preloader_test.rb → preloader_belongs_to_test.rb} +17 -15
- data/test/preloader_has_many_test.rb +13 -0
- data/test/preloader_has_one_test.rb +69 -0
- data/test/record_marshal_test.rb +1 -1
- data/test/test_helper.rb +3 -5
- metadata +31 -17
data/test/model/post.rb
CHANGED
data/test/model/topic.rb
CHANGED
data/test/model/user.rb
CHANGED
@@ -9,8 +9,7 @@ ActiveRecord::Base.connection.create_table(:users, force: true) do |t|
|
|
9
9
|
t.integer :status, default: 0
|
10
10
|
t.integer :books_count, default: 0
|
11
11
|
t.integer :images_count, default: 0
|
12
|
-
t.
|
13
|
-
t.timestamps null: false
|
12
|
+
t.timestamps null: false, precision: 6
|
14
13
|
end
|
15
14
|
|
16
15
|
ActiveRecord::Base.connection.create_table(:forked_user_links, force: true) do |t|
|
@@ -26,16 +25,15 @@ ActiveRecord::Base.connection.create_table(:namespaces, force: true) do |t|
|
|
26
25
|
t.timestamps null: false
|
27
26
|
end
|
28
27
|
|
29
|
-
class User <
|
28
|
+
class User < ApplicationRecord
|
30
29
|
CACHE_VERSION = 3
|
31
30
|
second_level_cache(version: CACHE_VERSION, expires_in: 3.days)
|
32
|
-
acts_as_paranoid
|
33
31
|
|
34
32
|
serialize :options, Array
|
35
33
|
serialize :json_options, JSON if ::ActiveRecord::VERSION::STRING >= "4.1.0"
|
36
34
|
store :extras, accessors: %i[tagline gender]
|
37
35
|
|
38
|
-
has_one :account
|
36
|
+
has_one :account, inverse_of: :user
|
39
37
|
has_one :forked_user_link, foreign_key: "forked_to_user_id"
|
40
38
|
has_one :forked_from_user, through: :forked_user_link
|
41
39
|
has_many :namespaces
|
@@ -46,13 +44,15 @@ class User < ActiveRecord::Base
|
|
46
44
|
enum status: %i[active archived]
|
47
45
|
end
|
48
46
|
|
49
|
-
class Namespace <
|
47
|
+
class Namespace < ApplicationRecord
|
50
48
|
second_level_cache version: 1, expires_in: 3.days
|
51
49
|
|
52
50
|
belongs_to :user
|
53
51
|
end
|
54
52
|
|
55
|
-
class ForkedUserLink <
|
53
|
+
class ForkedUserLink < ApplicationRecord
|
54
|
+
second_level_cache version: 1, expires_in: 1.day
|
55
|
+
|
56
56
|
belongs_to :forked_from_user, class_name: "User"
|
57
57
|
belongs_to :forked_to_user, class_name: "User"
|
58
58
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class ParanoidTest < ActiveSupport::TestCase
|
6
|
+
def setup
|
7
|
+
skip unless defined?(Paranoi)
|
8
|
+
@paranoid = Paranoid.create
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_should_expire_cache_when_destroy
|
12
|
+
skip unless defined(Paranoi)
|
13
|
+
@paranoid.destroy
|
14
|
+
assert_nil Paranoid.find_by(id: @paranoid.id)
|
15
|
+
assert_nil SecondLevelCache.cache_store.read(@paranoid.second_level_cache_key)
|
16
|
+
assert_nil User.read_second_level_cache(@paranoid.id)
|
17
|
+
end
|
18
|
+
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require "test_helper"
|
4
4
|
|
5
|
-
class
|
6
|
-
def
|
5
|
+
class PreloaderBelongsToTest < ActiveSupport::TestCase
|
6
|
+
def test_preload_caches_includes
|
7
7
|
topics = [
|
8
8
|
Topic.create(title: "title1", body: "body1"),
|
9
9
|
Topic.create(title: "title2", body: "body2"),
|
@@ -18,7 +18,7 @@ class PreloaderTest < ActiveSupport::TestCase
|
|
18
18
|
assert_equal topics, results.map(&:topic)
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def test_when_read_multi_missed_from_cache_ar_will_fetch_missed_records_from_db
|
22
22
|
topics = [
|
23
23
|
Topic.create(title: "title1", body: "body1"),
|
24
24
|
Topic.create(title: "title2", body: "body2"),
|
@@ -39,19 +39,21 @@ class PreloaderTest < ActiveSupport::TestCase
|
|
39
39
|
assert_equal topics, results.map(&:topic)
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
assert_equal
|
42
|
+
def test_preloader_caches_includes_tried_set_inverse_instance
|
43
|
+
user_id = Time.current.to_i
|
44
|
+
Account.create(site: "foobar", user_id: user_id)
|
45
|
+
User.create(id: user_id, name: "foobar", email: "foobar@test.com")
|
46
|
+
accounts = Account.includes(:user)
|
47
|
+
assert_equal accounts.first.object_id, accounts.first.user.account.object_id
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
user = User.create
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
def test_preloader_from_db_when_exists_scope
|
51
|
+
user = User.create
|
52
|
+
book = user.books.create
|
53
|
+
image = book.images.create
|
54
|
+
book.toggle!(:normal)
|
55
|
+
assert_queries(:any) do
|
56
|
+
assert_nil Image.includes(:imagable).where(id: image.id).first.imagable
|
57
|
+
end
|
56
58
|
end
|
57
59
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class PreloaderHasManyTest < ActiveSupport::TestCase
|
6
|
+
def test_preloader_returns_correct_records
|
7
|
+
topic = Topic.create(id: 1)
|
8
|
+
Post.create(id: 1)
|
9
|
+
post = topic.posts.create
|
10
|
+
|
11
|
+
assert_equal [post], Topic.includes(:posts).find(1).posts
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class PreloaderHasOneTest < ActiveSupport::TestCase
|
6
|
+
# def test_preload_caches_includes
|
7
|
+
# users = User.create([
|
8
|
+
# { name: "foobar1", email: "foobar1@test.com" },
|
9
|
+
# { name: "foobar2", email: "foobar2@test.com" },
|
10
|
+
# { name: "foobar3", email: "foobar3@test.com" }
|
11
|
+
# ])
|
12
|
+
# namespaces = users.map { |user| user.create_namespace(name: user.name) }
|
13
|
+
|
14
|
+
# assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
|
15
|
+
# assert_queries(1) do
|
16
|
+
# assert_equal namespaces, User.includes(:namespace).order(id: :asc).map(&:namespace)
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
|
20
|
+
# def test_when_read_multi_missed_from_cache_should_will_fetch_missed_records_from_db
|
21
|
+
# users = User.create([
|
22
|
+
# { name: "foobar1", email: "foobar1@test.com" },
|
23
|
+
# { name: "foobar2", email: "foobar2@test.com" },
|
24
|
+
# { name: "foobar3", email: "foobar3@test.com" }
|
25
|
+
# ])
|
26
|
+
# namespaces = users.map { |user| user.create_namespace(name: user.name) }
|
27
|
+
# assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
|
28
|
+
# expired_namespace = namespaces.first
|
29
|
+
# expired_namespace.expire_second_level_cache
|
30
|
+
|
31
|
+
# assert_queries(2) do
|
32
|
+
# assert_sql(/WHERE\s\"namespaces\".\"kind\"\sIS\sNULL\sAND\s\"namespaces\"\.\"user_id\"\s=\s?/m) do
|
33
|
+
# results = User.includes(:namespace).order(id: :asc).to_a
|
34
|
+
# assert_equal namespaces, results.map(&:namespace)
|
35
|
+
# assert_equal expired_namespace, results.first.namespace
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
|
40
|
+
# def test_preloader_returns_correct_records_after_modify
|
41
|
+
# user = User.create(name: "foobar", email: "foobar@test.com")
|
42
|
+
|
43
|
+
# old_namespace = user.create_namespace(name: "old")
|
44
|
+
# assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
|
45
|
+
# assert_queries(1) do
|
46
|
+
# assert_equal old_namespace, User.includes(:namespace).first.namespace
|
47
|
+
# end
|
48
|
+
|
49
|
+
# new_namespace = user.create_namespace(name: "new")
|
50
|
+
# assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
|
51
|
+
# assert_queries(1) do
|
52
|
+
# assert_equal new_namespace, User.includes(:namespace).first.namespace
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
|
56
|
+
# def test_preloader_caches_includes_tried_set_inverse_instance
|
57
|
+
# User.create(name: "foobar", email: "foobar@test.com").create_account(site: "foobar")
|
58
|
+
# users = User.includes(:account)
|
59
|
+
# assert_equal users.first.object_id, users.first.account.user.object_id
|
60
|
+
# end
|
61
|
+
|
62
|
+
def test_has_one_preloader_returns_correct_results
|
63
|
+
user = User.create(id: 1)
|
64
|
+
Account.create(id: 1)
|
65
|
+
account = user.create_account
|
66
|
+
|
67
|
+
assert_equal account, User.includes(:account).find(1).account
|
68
|
+
end
|
69
|
+
end
|
data/test/record_marshal_test.rb
CHANGED
@@ -25,7 +25,7 @@ class RecordMarshalTest < ActiveSupport::TestCase
|
|
25
25
|
dumped = RecordMarshal.dump(@user)
|
26
26
|
assert dumped.is_a?(Array)
|
27
27
|
assert_equal "User", dumped[0]
|
28
|
-
assert_equal
|
28
|
+
assert_equal dumped[1], ActiveRecord::Base.connection.select_all(User.where(id: @user.id)).first
|
29
29
|
end
|
30
30
|
|
31
31
|
def test_should_load_active_record_object
|
data/test/test_helper.rb
CHANGED
@@ -6,7 +6,6 @@ require "active_support/test_case"
|
|
6
6
|
require "active_record_test_case_helper"
|
7
7
|
require "database_cleaner"
|
8
8
|
require "active_record"
|
9
|
-
require "paranoia"
|
10
9
|
require "pry"
|
11
10
|
ActiveSupport.test_order = :sorted if ActiveSupport.respond_to?(:test_order=)
|
12
11
|
# Force hook :active_record on_load event to make sure loader can work.
|
@@ -16,6 +15,7 @@ require "second_level_cache"
|
|
16
15
|
|
17
16
|
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
18
17
|
|
18
|
+
require "model/application_record"
|
19
19
|
require "model/user"
|
20
20
|
require "model/book"
|
21
21
|
require "model/image"
|
@@ -25,6 +25,8 @@ require "model/order"
|
|
25
25
|
require "model/order_item"
|
26
26
|
require "model/account"
|
27
27
|
require "model/animal"
|
28
|
+
require "model/contribution"
|
29
|
+
require "model/paranoid" if defined?(Paranoid)
|
28
30
|
|
29
31
|
DatabaseCleaner[:active_record].strategy = :truncation
|
30
32
|
|
@@ -32,10 +34,6 @@ SecondLevelCache.configure do |config|
|
|
32
34
|
config.cache_store = ActiveSupport::Cache::MemoryStore.new
|
33
35
|
end
|
34
36
|
|
35
|
-
SecondLevelCache.logger.level = Logger::ERROR
|
36
|
-
ActiveSupport::Cache::MemoryStore.logger = SecondLevelCache.logger
|
37
|
-
ActiveRecord::Base.logger = SecondLevelCache.logger
|
38
|
-
|
39
37
|
module ActiveSupport
|
40
38
|
class TestCase
|
41
39
|
setup do
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: second_level_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hooopo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '7'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: activesupport
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
@@ -51,19 +51,19 @@ dependencies:
|
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '7'
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
54
|
+
name: database_cleaner
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
|
-
- - "
|
57
|
+
- - ">="
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: '
|
59
|
+
version: '0'
|
60
60
|
type: :development
|
61
61
|
prerelease: false
|
62
62
|
version_requirements: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
|
-
- - "
|
64
|
+
- - ">="
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
66
|
+
version: '0'
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: rake
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,7 +79,7 @@ dependencies:
|
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: '0'
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
|
-
name:
|
82
|
+
name: rubocop
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
85
|
- - ">="
|
@@ -93,19 +93,19 @@ dependencies:
|
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '0'
|
95
95
|
- !ruby/object:Gem::Dependency
|
96
|
-
name:
|
96
|
+
name: sqlite3
|
97
97
|
requirement: !ruby/object:Gem::Requirement
|
98
98
|
requirements:
|
99
|
-
- - "
|
99
|
+
- - ">"
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
101
|
+
version: '1.4'
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
requirements:
|
106
|
-
- - "
|
106
|
+
- - ">"
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version:
|
108
|
+
version: '1.4'
|
109
109
|
description: Write Through and Read Through caching library inspired by CacheMoney
|
110
110
|
and cache_fu, support ActiveRecord 4.
|
111
111
|
email:
|
@@ -128,7 +128,9 @@ files:
|
|
128
128
|
- lib/second_level_cache/active_record/has_one_association.rb
|
129
129
|
- lib/second_level_cache/active_record/persistence.rb
|
130
130
|
- lib/second_level_cache/active_record/preloader.rb
|
131
|
+
- lib/second_level_cache/adapter/paranoia.rb
|
131
132
|
- lib/second_level_cache/config.rb
|
133
|
+
- lib/second_level_cache/log_subscriber.rb
|
132
134
|
- lib/second_level_cache/mixin.rb
|
133
135
|
- lib/second_level_cache/record_marshal.rb
|
134
136
|
- lib/second_level_cache/record_relation.rb
|
@@ -143,17 +145,23 @@ files:
|
|
143
145
|
- test/has_one_association_test.rb
|
144
146
|
- test/model/account.rb
|
145
147
|
- test/model/animal.rb
|
148
|
+
- test/model/application_record.rb
|
146
149
|
- test/model/book.rb
|
150
|
+
- test/model/contribution.rb
|
147
151
|
- test/model/image.rb
|
148
152
|
- test/model/order.rb
|
149
153
|
- test/model/order_item.rb
|
154
|
+
- test/model/paranoid.rb
|
150
155
|
- test/model/post.rb
|
151
156
|
- test/model/topic.rb
|
152
157
|
- test/model/user.rb
|
158
|
+
- test/paranoid_test.rb
|
153
159
|
- test/persistence_test.rb
|
154
160
|
- test/polymorphic_association_test.rb
|
161
|
+
- test/preloader_belongs_to_test.rb
|
162
|
+
- test/preloader_has_many_test.rb
|
163
|
+
- test/preloader_has_one_test.rb
|
155
164
|
- test/preloader_non_integer_test.rb
|
156
|
-
- test/preloader_test.rb
|
157
165
|
- test/record_marshal_test.rb
|
158
166
|
- test/require_test.rb
|
159
167
|
- test/second_level_cache_test.rb
|
@@ -187,24 +195,30 @@ summary: 'SecondLevelCache is a write-through and read-through caching library i
|
|
187
195
|
is a cache miss, it will populate the cache. Write-Through: As objects are created,
|
188
196
|
updated, and deleted, all of the caches are automatically kept up-to-date and coherent.'
|
189
197
|
test_files:
|
198
|
+
- test/preloader_belongs_to_test.rb
|
190
199
|
- test/polymorphic_association_test.rb
|
191
200
|
- test/require_test.rb
|
192
|
-
- test/
|
201
|
+
- test/paranoid_test.rb
|
193
202
|
- test/finder_methods_test.rb
|
203
|
+
- test/preloader_has_one_test.rb
|
194
204
|
- test/preloader_non_integer_test.rb
|
195
205
|
- test/belongs_to_association_test.rb
|
196
206
|
- test/second_level_cache_test.rb
|
197
207
|
- test/enum_attr_test.rb
|
198
208
|
- test/record_marshal_test.rb
|
209
|
+
- test/preloader_has_many_test.rb
|
199
210
|
- test/persistence_test.rb
|
200
211
|
- test/single_table_inheritance_test.rb
|
201
212
|
- test/model/image.rb
|
202
213
|
- test/model/account.rb
|
203
214
|
- test/model/order_item.rb
|
215
|
+
- test/model/contribution.rb
|
204
216
|
- test/model/book.rb
|
205
217
|
- test/model/topic.rb
|
206
218
|
- test/model/animal.rb
|
207
219
|
- test/model/order.rb
|
220
|
+
- test/model/paranoid.rb
|
221
|
+
- test/model/application_record.rb
|
208
222
|
- test/model/post.rb
|
209
223
|
- test/model/user.rb
|
210
224
|
- test/fetch_by_uniq_key_test.rb
|