second_level_cache 2.5.3 → 2.6.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/CHANGELOG.md +29 -0
- data/README.md +4 -4
- 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 +14 -27
- data/lib/second_level_cache/active_record/finder_methods.rb +44 -42
- data/lib/second_level_cache/active_record/has_one_association.rb +15 -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 +1 -1
- data/test/fetch_by_uniq_key_test.rb +18 -14
- data/test/finder_methods_test.rb +39 -0
- data/test/has_one_association_test.rb +20 -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 +4 -1
- data/test/model/contribution.rb +1 -1
- 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 +11 -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 +2 -5
- metadata +33 -21
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"
|
@@ -26,6 +26,7 @@ require "model/order_item"
|
|
26
26
|
require "model/account"
|
27
27
|
require "model/animal"
|
28
28
|
require "model/contribution"
|
29
|
+
require "model/paranoid" if defined?(Paranoid)
|
29
30
|
|
30
31
|
DatabaseCleaner[:active_record].strategy = :truncation
|
31
32
|
|
@@ -33,10 +34,6 @@ SecondLevelCache.configure do |config|
|
|
33
34
|
config.cache_store = ActiveSupport::Cache::MemoryStore.new
|
34
35
|
end
|
35
36
|
|
36
|
-
SecondLevelCache.logger.level = Logger::ERROR
|
37
|
-
ActiveSupport::Cache::MemoryStore.logger = SecondLevelCache.logger
|
38
|
-
ActiveRecord::Base.logger = SecondLevelCache.logger
|
39
|
-
|
40
37
|
module ActiveSupport
|
41
38
|
class TestCase
|
42
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.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hooopo
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-10 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,18 +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
|
147
150
|
- test/model/contribution.rb
|
148
151
|
- test/model/image.rb
|
149
152
|
- test/model/order.rb
|
150
153
|
- test/model/order_item.rb
|
154
|
+
- test/model/paranoid.rb
|
151
155
|
- test/model/post.rb
|
152
156
|
- test/model/topic.rb
|
153
157
|
- test/model/user.rb
|
158
|
+
- test/paranoid_test.rb
|
154
159
|
- test/persistence_test.rb
|
155
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
|
156
164
|
- test/preloader_non_integer_test.rb
|
157
|
-
- test/preloader_test.rb
|
158
165
|
- test/record_marshal_test.rb
|
159
166
|
- test/require_test.rb
|
160
167
|
- test/second_level_cache_test.rb
|
@@ -163,7 +170,7 @@ files:
|
|
163
170
|
homepage: https://github.com/hooopo/second_level_cache
|
164
171
|
licenses: []
|
165
172
|
metadata: {}
|
166
|
-
post_install_message:
|
173
|
+
post_install_message:
|
167
174
|
rdoc_options: []
|
168
175
|
require_paths:
|
169
176
|
- lib
|
@@ -178,8 +185,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
185
|
- !ruby/object:Gem::Version
|
179
186
|
version: '0'
|
180
187
|
requirements: []
|
181
|
-
rubygems_version: 3.
|
182
|
-
signing_key:
|
188
|
+
rubygems_version: 3.1.2
|
189
|
+
signing_key:
|
183
190
|
specification_version: 4
|
184
191
|
summary: 'SecondLevelCache is a write-through and read-through caching library inspired
|
185
192
|
by Cache Money and cache_fu, support only Rails3 and ActiveRecord. Read-Through:
|
@@ -188,15 +195,18 @@ summary: 'SecondLevelCache is a write-through and read-through caching library i
|
|
188
195
|
is a cache miss, it will populate the cache. Write-Through: As objects are created,
|
189
196
|
updated, and deleted, all of the caches are automatically kept up-to-date and coherent.'
|
190
197
|
test_files:
|
198
|
+
- test/preloader_belongs_to_test.rb
|
191
199
|
- test/polymorphic_association_test.rb
|
192
200
|
- test/require_test.rb
|
193
|
-
- test/
|
201
|
+
- test/paranoid_test.rb
|
194
202
|
- test/finder_methods_test.rb
|
203
|
+
- test/preloader_has_one_test.rb
|
195
204
|
- test/preloader_non_integer_test.rb
|
196
205
|
- test/belongs_to_association_test.rb
|
197
206
|
- test/second_level_cache_test.rb
|
198
207
|
- test/enum_attr_test.rb
|
199
208
|
- test/record_marshal_test.rb
|
209
|
+
- test/preloader_has_many_test.rb
|
200
210
|
- test/persistence_test.rb
|
201
211
|
- test/single_table_inheritance_test.rb
|
202
212
|
- test/model/image.rb
|
@@ -207,6 +217,8 @@ test_files:
|
|
207
217
|
- test/model/topic.rb
|
208
218
|
- test/model/animal.rb
|
209
219
|
- test/model/order.rb
|
220
|
+
- test/model/paranoid.rb
|
221
|
+
- test/model/application_record.rb
|
210
222
|
- test/model/post.rb
|
211
223
|
- test/model/user.rb
|
212
224
|
- test/fetch_by_uniq_key_test.rb
|