ar_cache 1.1.0 → 2.0.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 +4 -4
- data/CHANGELOG.md +0 -10
- data/Gemfile.common +2 -0
- data/Gemfile.lock +89 -80
- data/README.md +20 -6
- data/README.zh-CN.md +165 -0
- data/ar_cache.gemspec +1 -0
- data/lib/ar_cache.rb +42 -15
- data/lib/ar_cache/active_record/associations/has_one_through_association.rb +10 -7
- data/lib/ar_cache/active_record/associations/singular_association.rb +2 -4
- data/lib/ar_cache/active_record/connection_adapters/abstract/database_statements.rb +20 -15
- data/lib/ar_cache/active_record/connection_adapters/abstract/transaction.rb +37 -32
- data/lib/ar_cache/active_record/core.rb +4 -5
- data/lib/ar_cache/active_record/insert_all.rb +1 -4
- data/lib/ar_cache/active_record/model_schema.rb +1 -7
- data/lib/ar_cache/active_record/persistence.rb +3 -4
- data/lib/ar_cache/active_record/relation.rb +7 -14
- data/lib/ar_cache/configuration.rb +34 -42
- data/lib/ar_cache/marshal.rb +28 -26
- data/lib/ar_cache/mock_table.rb +4 -12
- data/lib/ar_cache/query.rb +25 -15
- data/lib/ar_cache/table.rb +45 -60
- data/lib/ar_cache/version.rb +1 -1
- data/lib/ar_cache/where_clause.rb +35 -26
- data/lib/generators/ar_cache/install_generator.rb +0 -7
- data/lib/generators/ar_cache/templates/configuration.rb +20 -25
- metadata +23 -5
- data/lib/ar_cache/record.rb +0 -54
- data/lib/ar_cache/store.rb +0 -38
- data/lib/generators/ar_cache/templates/migrate/create_ar_cache_records.rb.tt +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4d25cbd1abb845a90dbd29d50d1dfb5b622e454e6c0bfe4a1ae65b4eddb818f
|
4
|
+
data.tar.gz: 821f3036d2df0db1f143a3212cffacf306ac30aa2335385defde6b41edf5f46d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0a9706501fa606ee7cf02931bdbfc5efd3e2668fb5b51c55b971d616233b43595363b30ccf279d500df64789268398c140870c8683b7e79e8b70717ebd2983a
|
7
|
+
data.tar.gz: 46e0a6c9a76401dec6d2f3c11f52e4e9a3e0d1b975c827df7eca05f0068612d78755238db00c5f170ab30523c5aee15eb6556b3956599490d0a812d4f8d917d5
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,3 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
3
|
## main
|
4
|
-
|
5
|
-
## 1.0.0 (2021-03-02)
|
6
|
-
|
7
|
-
- Initial version.
|
8
|
-
|
9
|
-
## 1.1.0 (2021-03-11)
|
10
|
-
|
11
|
-
- Fully automatic delete cache when call delete_all/update_all method.
|
12
|
-
- Optimize has_one(through:) cache implementation.
|
13
|
-
- ActiveRecord::Relation#reload and ActiveRecord::Associations::Association#reload should skip read cache if associated target is already loaded.
|
data/Gemfile.common
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,66 +1,67 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ar_cache (
|
4
|
+
ar_cache (2.0.0)
|
5
5
|
activerecord (>= 6.1, < 7)
|
6
|
+
oj (>= 3, < 4)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
|
-
actioncable (6.1.
|
11
|
-
actionpack (= 6.1.
|
12
|
-
activesupport (= 6.1.
|
11
|
+
actioncable (6.1.3.2)
|
12
|
+
actionpack (= 6.1.3.2)
|
13
|
+
activesupport (= 6.1.3.2)
|
13
14
|
nio4r (~> 2.0)
|
14
15
|
websocket-driver (>= 0.6.1)
|
15
|
-
actionmailbox (6.1.
|
16
|
-
actionpack (= 6.1.
|
17
|
-
activejob (= 6.1.
|
18
|
-
activerecord (= 6.1.
|
19
|
-
activestorage (= 6.1.
|
20
|
-
activesupport (= 6.1.
|
16
|
+
actionmailbox (6.1.3.2)
|
17
|
+
actionpack (= 6.1.3.2)
|
18
|
+
activejob (= 6.1.3.2)
|
19
|
+
activerecord (= 6.1.3.2)
|
20
|
+
activestorage (= 6.1.3.2)
|
21
|
+
activesupport (= 6.1.3.2)
|
21
22
|
mail (>= 2.7.1)
|
22
|
-
actionmailer (6.1.
|
23
|
-
actionpack (= 6.1.
|
24
|
-
actionview (= 6.1.
|
25
|
-
activejob (= 6.1.
|
26
|
-
activesupport (= 6.1.
|
23
|
+
actionmailer (6.1.3.2)
|
24
|
+
actionpack (= 6.1.3.2)
|
25
|
+
actionview (= 6.1.3.2)
|
26
|
+
activejob (= 6.1.3.2)
|
27
|
+
activesupport (= 6.1.3.2)
|
27
28
|
mail (~> 2.5, >= 2.5.4)
|
28
29
|
rails-dom-testing (~> 2.0)
|
29
|
-
actionpack (6.1.
|
30
|
-
actionview (= 6.1.
|
31
|
-
activesupport (= 6.1.
|
30
|
+
actionpack (6.1.3.2)
|
31
|
+
actionview (= 6.1.3.2)
|
32
|
+
activesupport (= 6.1.3.2)
|
32
33
|
rack (~> 2.0, >= 2.0.9)
|
33
34
|
rack-test (>= 0.6.3)
|
34
35
|
rails-dom-testing (~> 2.0)
|
35
36
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
36
|
-
actiontext (6.1.
|
37
|
-
actionpack (= 6.1.
|
38
|
-
activerecord (= 6.1.
|
39
|
-
activestorage (= 6.1.
|
40
|
-
activesupport (= 6.1.
|
37
|
+
actiontext (6.1.3.2)
|
38
|
+
actionpack (= 6.1.3.2)
|
39
|
+
activerecord (= 6.1.3.2)
|
40
|
+
activestorage (= 6.1.3.2)
|
41
|
+
activesupport (= 6.1.3.2)
|
41
42
|
nokogiri (>= 1.8.5)
|
42
|
-
actionview (6.1.
|
43
|
-
activesupport (= 6.1.
|
43
|
+
actionview (6.1.3.2)
|
44
|
+
activesupport (= 6.1.3.2)
|
44
45
|
builder (~> 3.1)
|
45
46
|
erubi (~> 1.4)
|
46
47
|
rails-dom-testing (~> 2.0)
|
47
48
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
48
|
-
activejob (6.1.
|
49
|
-
activesupport (= 6.1.
|
49
|
+
activejob (6.1.3.2)
|
50
|
+
activesupport (= 6.1.3.2)
|
50
51
|
globalid (>= 0.3.6)
|
51
|
-
activemodel (6.1.
|
52
|
-
activesupport (= 6.1.
|
53
|
-
activerecord (6.1.
|
54
|
-
activemodel (= 6.1.
|
55
|
-
activesupport (= 6.1.
|
56
|
-
activestorage (6.1.
|
57
|
-
actionpack (= 6.1.
|
58
|
-
activejob (= 6.1.
|
59
|
-
activerecord (= 6.1.
|
60
|
-
activesupport (= 6.1.
|
61
|
-
marcel (~> 0.
|
62
|
-
|
63
|
-
activesupport (6.1.
|
52
|
+
activemodel (6.1.3.2)
|
53
|
+
activesupport (= 6.1.3.2)
|
54
|
+
activerecord (6.1.3.2)
|
55
|
+
activemodel (= 6.1.3.2)
|
56
|
+
activesupport (= 6.1.3.2)
|
57
|
+
activestorage (6.1.3.2)
|
58
|
+
actionpack (= 6.1.3.2)
|
59
|
+
activejob (= 6.1.3.2)
|
60
|
+
activerecord (= 6.1.3.2)
|
61
|
+
activesupport (= 6.1.3.2)
|
62
|
+
marcel (~> 1.0.0)
|
63
|
+
mini_mime (~> 1.0.2)
|
64
|
+
activesupport (6.1.3.2)
|
64
65
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
65
66
|
i18n (>= 1.6, < 2)
|
66
67
|
minitest (>= 5.1)
|
@@ -71,86 +72,92 @@ GEM
|
|
71
72
|
coderay (1.1.3)
|
72
73
|
concurrent-ruby (1.1.8)
|
73
74
|
crass (1.0.6)
|
74
|
-
|
75
|
+
dalli (2.7.11)
|
76
|
+
database_cleaner (2.0.1)
|
77
|
+
database_cleaner-active_record (~> 2.0.0)
|
78
|
+
database_cleaner-active_record (2.0.1)
|
79
|
+
activerecord (>= 5.a)
|
80
|
+
database_cleaner-core (~> 2.0.0)
|
81
|
+
database_cleaner-core (2.0.1)
|
75
82
|
erubi (1.10.0)
|
76
83
|
globalid (0.4.2)
|
77
84
|
activesupport (>= 4.2.0)
|
78
|
-
i18n (1.8.
|
85
|
+
i18n (1.8.10)
|
79
86
|
concurrent-ruby (~> 1.0)
|
80
|
-
loofah (2.9.
|
87
|
+
loofah (2.9.1)
|
81
88
|
crass (~> 1.0.2)
|
82
89
|
nokogiri (>= 1.5.9)
|
83
90
|
mail (2.7.1)
|
84
91
|
mini_mime (>= 0.1.1)
|
85
|
-
marcel (0.
|
86
|
-
mimemagic (~> 0.3.2)
|
92
|
+
marcel (1.0.1)
|
87
93
|
method_source (1.0.0)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
nokogiri (1.11.1-x86_64-linux)
|
94
|
+
mini_mime (1.0.3)
|
95
|
+
minitest (5.14.4)
|
96
|
+
nio4r (2.5.7)
|
97
|
+
nokogiri (1.11.6-x86_64-linux)
|
93
98
|
racc (~> 1.4)
|
99
|
+
oj (3.11.5)
|
94
100
|
parallel (1.20.1)
|
95
|
-
parser (3.0.
|
101
|
+
parser (3.0.1.1)
|
96
102
|
ast (~> 2.4.1)
|
97
|
-
pry (0.
|
103
|
+
pry (0.14.1)
|
98
104
|
coderay (~> 1.1)
|
99
105
|
method_source (~> 1.0)
|
100
106
|
racc (1.5.2)
|
101
107
|
rack (2.2.3)
|
102
108
|
rack-test (1.1.0)
|
103
109
|
rack (>= 1.0, < 3)
|
104
|
-
rails (6.1.
|
105
|
-
actioncable (= 6.1.
|
106
|
-
actionmailbox (= 6.1.
|
107
|
-
actionmailer (= 6.1.
|
108
|
-
actionpack (= 6.1.
|
109
|
-
actiontext (= 6.1.
|
110
|
-
actionview (= 6.1.
|
111
|
-
activejob (= 6.1.
|
112
|
-
activemodel (= 6.1.
|
113
|
-
activerecord (= 6.1.
|
114
|
-
activestorage (= 6.1.
|
115
|
-
activesupport (= 6.1.
|
110
|
+
rails (6.1.3.2)
|
111
|
+
actioncable (= 6.1.3.2)
|
112
|
+
actionmailbox (= 6.1.3.2)
|
113
|
+
actionmailer (= 6.1.3.2)
|
114
|
+
actionpack (= 6.1.3.2)
|
115
|
+
actiontext (= 6.1.3.2)
|
116
|
+
actionview (= 6.1.3.2)
|
117
|
+
activejob (= 6.1.3.2)
|
118
|
+
activemodel (= 6.1.3.2)
|
119
|
+
activerecord (= 6.1.3.2)
|
120
|
+
activestorage (= 6.1.3.2)
|
121
|
+
activesupport (= 6.1.3.2)
|
116
122
|
bundler (>= 1.15.0)
|
117
|
-
railties (= 6.1.
|
123
|
+
railties (= 6.1.3.2)
|
118
124
|
sprockets-rails (>= 2.0.0)
|
119
125
|
rails-dom-testing (2.0.3)
|
120
126
|
activesupport (>= 4.2.0)
|
121
127
|
nokogiri (>= 1.6)
|
122
128
|
rails-html-sanitizer (1.3.0)
|
123
129
|
loofah (~> 2.3)
|
124
|
-
railties (6.1.
|
125
|
-
actionpack (= 6.1.
|
126
|
-
activesupport (= 6.1.
|
130
|
+
railties (6.1.3.2)
|
131
|
+
actionpack (= 6.1.3.2)
|
132
|
+
activesupport (= 6.1.3.2)
|
127
133
|
method_source
|
128
134
|
rake (>= 0.8.7)
|
129
135
|
thor (~> 1.0)
|
130
136
|
rainbow (3.0.0)
|
131
137
|
rake (13.0.3)
|
138
|
+
redis (4.2.5)
|
132
139
|
regexp_parser (2.1.1)
|
133
|
-
rexml (3.2.
|
134
|
-
rubocop (1.
|
140
|
+
rexml (3.2.5)
|
141
|
+
rubocop (1.15.0)
|
135
142
|
parallel (~> 1.10)
|
136
143
|
parser (>= 3.0.0.0)
|
137
144
|
rainbow (>= 2.2.2, < 4.0)
|
138
145
|
regexp_parser (>= 1.8, < 3.0)
|
139
146
|
rexml
|
140
|
-
rubocop-ast (>= 1.
|
147
|
+
rubocop-ast (>= 1.5.0, < 2.0)
|
141
148
|
ruby-progressbar (~> 1.7)
|
142
149
|
unicode-display_width (>= 1.4.0, < 3.0)
|
143
|
-
rubocop-ast (1.
|
144
|
-
parser (>=
|
145
|
-
rubocop-minitest (0.
|
146
|
-
rubocop (>= 0.
|
147
|
-
rubocop-performance (1.
|
148
|
-
rubocop (>=
|
150
|
+
rubocop-ast (1.6.0)
|
151
|
+
parser (>= 3.0.1.1)
|
152
|
+
rubocop-minitest (0.12.1)
|
153
|
+
rubocop (>= 0.90, < 2.0)
|
154
|
+
rubocop-performance (1.11.3)
|
155
|
+
rubocop (>= 1.7.0, < 2.0)
|
149
156
|
rubocop-ast (>= 0.4.0)
|
150
|
-
rubocop-rails (2.
|
157
|
+
rubocop-rails (2.10.1)
|
151
158
|
activesupport (>= 4.2.0)
|
152
159
|
rack (>= 1.1)
|
153
|
-
rubocop (>=
|
160
|
+
rubocop (>= 1.7.0, < 2.0)
|
154
161
|
rubocop-rake (0.5.1)
|
155
162
|
rubocop
|
156
163
|
ruby-progressbar (1.11.0)
|
@@ -166,7 +173,7 @@ GEM
|
|
166
173
|
tzinfo (2.0.4)
|
167
174
|
concurrent-ruby (~> 1.0)
|
168
175
|
unicode-display_width (2.0.0)
|
169
|
-
websocket-driver (0.7.
|
176
|
+
websocket-driver (0.7.4)
|
170
177
|
websocket-extensions (>= 0.1.0)
|
171
178
|
websocket-extensions (0.1.5)
|
172
179
|
zeitwerk (2.4.2)
|
@@ -176,11 +183,13 @@ PLATFORMS
|
|
176
183
|
|
177
184
|
DEPENDENCIES
|
178
185
|
ar_cache!
|
186
|
+
dalli
|
179
187
|
database_cleaner
|
180
188
|
minitest
|
181
189
|
pry
|
182
190
|
rails
|
183
191
|
rake
|
192
|
+
redis
|
184
193
|
rubocop
|
185
194
|
rubocop-minitest
|
186
195
|
rubocop-performance
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# ArCache
|
1
|
+
# ArCache (This is outdated, please see [中文文档](README.zh-CN.md))
|
2
2
|
|
3
3
|

|
4
4
|
[](https://badge.fury.io/rb/ar_cache)
|
@@ -16,7 +16,7 @@ then query the database and write the result to the cache.
|
|
16
16
|
- `Read cache`: Automatically intercept ActiveRecord queries, then try to fetch data from cache.
|
17
17
|
- `Write cache`: If the query is cacheable and the cached data is not exists, it will be automatically written to the cache after the query.
|
18
18
|
- `Expire cache`: Automatically expire cache after updated/modified data.
|
19
|
-
- `Iterative cache`: The cache version will be updated after table fields
|
19
|
+
- `Iterative cache`: The cache version will be updated after table fields or `ArCache` switch changed.
|
20
20
|
- `Shared cache`: The cache is not only used with ActiveRecord, you can easily use it in other places.([see examples](examples))
|
21
21
|
|
22
22
|
## Installation
|
@@ -55,17 +55,31 @@ rake db:migrate
|
|
55
55
|
|
56
56
|
Skip cache:
|
57
57
|
|
58
|
+
- `ArCache#skip_cache`, eg:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
# All queries in the block will not use the cache.
|
62
|
+
ArCache.skip_cache { User.find(1) }
|
63
|
+
```
|
64
|
+
|
58
65
|
- `ActiveRecord::Persistence#reload`, eg:
|
59
66
|
|
60
67
|
```ruby
|
61
68
|
User.find(1).reload
|
62
69
|
```
|
63
70
|
|
64
|
-
- `ActiveRecord::Relation#
|
71
|
+
- `ActiveRecord::Relation#reload`, eg:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# When reload is called after the associated target has been loaded, the cache will be skipped.
|
75
|
+
User.where(id: 1).load.reload
|
76
|
+
```
|
77
|
+
|
78
|
+
- `ActiveRecord::Associations::Association#reload`, eg:
|
65
79
|
|
66
80
|
```ruby
|
67
|
-
|
68
|
-
|
81
|
+
# When reload is called after the associated target has been loaded, the cache will be skipped.
|
82
|
+
user.association(:account).load_target.reload
|
69
83
|
```
|
70
84
|
|
71
85
|
Delete cache:
|
@@ -91,7 +105,7 @@ If all the following conditions are met, ArCache will try to read the cache:
|
|
91
105
|
- No call `#select` or select value is table column.
|
92
106
|
- No call `#order` or order value is table column and only one.
|
93
107
|
- No call `#limit` or value of the unique index isn't array.
|
94
|
-
- No call `#joins`, `#left_joins`, `#skip_query_cache!`, `#
|
108
|
+
- No call `#joins`, `#left_joins`, `#skip_query_cache!`, `#explain`, `#from`, `#group`, `#offset`, `#lock`
|
95
109
|
- ...
|
96
110
|
|
97
111
|
**Cacheable example:**
|
data/README.zh-CN.md
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
# ArCache
|
2
|
+
|
3
|
+

|
4
|
+
[](https://badge.fury.io/rb/ar_cache)
|
5
|
+
|
6
|
+
`ArCache` 是一个现代的 `ActiveRecord` 查询缓存库,它受 [`cache-money`](https://github.com/ngmoco/cache-money) 和 [`second_level_cache`](https://github.com/hooopo/second_level_cache) 的启发而创作。
|
7
|
+
当 `ActiveRecord` 实例化查询条件命中唯一索引时,`ArCache` 会拦截此次查询,尝试从缓存中获取结果;如果缓存缺失,
|
8
|
+
将在 `ActiveRecord` 查询完成后自动填充缓存。
|
9
|
+
`ArCache` 会自动维护缓存的正确性。
|
10
|
+
|
11
|
+
## 特点
|
12
|
+
|
13
|
+
- **低影响**:如果项目里数据库操作的相关代码符合 `ActiveRecord` 风格的话,那么你可以直接引入 `ArCache`,无需修改任何代码。([详细](#警告))
|
14
|
+
- **读缓存**:当实例化查询的条件命中唯一索引时,`ArCache` 会尝试从缓存中获取结果返回。
|
15
|
+
- **写缓存**:当读缓存操作没有获取到结果时,`ArCache` 会在 `ActiveRecord` 查询操作结束后,写入缓存。
|
16
|
+
- **删缓存**:在更新或删除数据后,`ArCache` 会自动移除对应的缓存。
|
17
|
+
- **迭代缓存**:当表结构发生改变后,`ArCache` 会更新这个表对应的缓存版本。
|
18
|
+
- **共享缓存**:`ArCache` 里面缓存是完整表字段与数据的哈希结果的 `json` 序列化字符串(仅当使用 `redis/memcached` 作为存储器时),因此缓存的使用是没有局限的。([实例](examples))
|
19
|
+
|
20
|
+
## 安装
|
21
|
+
|
22
|
+
向项目的 `Gemfile` 文件里增加一行内容:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
gem 'ar_cache'
|
26
|
+
```
|
27
|
+
|
28
|
+
之后,执行:
|
29
|
+
|
30
|
+
```shell
|
31
|
+
bundle install
|
32
|
+
```
|
33
|
+
|
34
|
+
## 初始化配置文件
|
35
|
+
|
36
|
+
如果是 `rails` 项目,直接执行命令:
|
37
|
+
|
38
|
+
```shell
|
39
|
+
rails generate ar_cache:install
|
40
|
+
```
|
41
|
+
|
42
|
+
不是,则将 [configuration.rb](lib/generators/ar_cache/templates/configuration.rb) 文件手动复制到项目对应的目录。
|
43
|
+
|
44
|
+
## 配置项
|
45
|
+
|
46
|
+
关于配置项的说明,请直接查看 [configuration.rb](lib/generators/ar_cache/templates/configuration.rb) 文件.
|
47
|
+
|
48
|
+
## 用法
|
49
|
+
|
50
|
+
只需要了解如何删除缓存和跳过缓存即可。
|
51
|
+
|
52
|
+
删除缓存:
|
53
|
+
|
54
|
+
- `ArCache::Table#delete`, 例如:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
User.ar_cache_table.delete(id...)
|
58
|
+
User.first.ar_cache_table.delete(id...)
|
59
|
+
```
|
60
|
+
|
61
|
+
跳过缓存:
|
62
|
+
|
63
|
+
- `ArCache#skip_cache`, 例如:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
ArCache.skip_cache do
|
67
|
+
# 块里面的全部查询将跳过缓存
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
- `ActiveRecord::Persistence#reload`, 例如:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
User.find(1).reload
|
75
|
+
```
|
76
|
+
|
77
|
+
- `ActiveRecord::Relation#reload`, 例如:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
# 当 relation 已加载查询后,再调用 reload 方法时,将跳过缓存
|
81
|
+
User.where(id: 1).load.reload
|
82
|
+
```
|
83
|
+
|
84
|
+
- `ActiveRecord::Associations::Association#reload`, 例如:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
# 当关联对象已加载查询后,再调用 reload 方法时,将跳过缓存
|
88
|
+
user.association(:account).load_target.reload
|
89
|
+
```
|
90
|
+
|
91
|
+
## 可读缓存的查询
|
92
|
+
|
93
|
+
必须满足下列全部条件:
|
94
|
+
|
95
|
+
- 使用哈希作为查询条件
|
96
|
+
- 查询条件包含唯一索引
|
97
|
+
- 没有事务存在,或者事务里面没有查询表的更新或删除操作(后续会尝试解除这个限制)
|
98
|
+
- 没有调用过 `select` 方法,或者 `select` 字段都是表字段
|
99
|
+
- 没有调用过 `order/order!` 方法,或者 `order` 字段只有一个,并且该字段是表字段
|
100
|
+
- 没有调用过 `limit/limit!` 方法,或者查询条件只能命中一个结果
|
101
|
+
- 没有调用过 `skip_query_cache!` 方法
|
102
|
+
- 没有调用过 `lock/lock!` 方法
|
103
|
+
- 没有调用过 `distinct/distinct!` 方法
|
104
|
+
- 没有调用过 `group/group!` 方法
|
105
|
+
- 没有调用过 `joins/joins!` 方法
|
106
|
+
- 没有调用过 `left_outer_joins/left_outer_joins!` 方法
|
107
|
+
- 没有调用过 `offset/offset!` 方法
|
108
|
+
- 没有调用过 `eager_load/eager_load!` 方法
|
109
|
+
- 没有调用过 `references/references!` 方法
|
110
|
+
- 没有调用过 `from/from!` 方法
|
111
|
+
- ...
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
User.find(1) # 主键查询是可读缓存的
|
115
|
+
User.where(email: 'foobar@gmail.com') # 唯一索引查询是可读缓存的
|
116
|
+
User.where(id: [1, 2]) # 唯一索引有多个值的情况,依然是可读缓存的
|
117
|
+
User.where(name: 'foobar', status: :active) # 联合字段的唯一索引查询是可读缓存的
|
118
|
+
User.includes(:account).where(id: [1, 2]) # ActiveRecord 的预加载是可读缓存的(仅当为 has_one 关联时)
|
119
|
+
User.first.account # ActiveRecord 的关联对象是可读缓存的(仅当为 has_one 关联时)
|
120
|
+
```
|
121
|
+
|
122
|
+
注意: `has_many` 的关联缓存,目前是不支持的,后续会尝试支持,但希望不大。
|
123
|
+
|
124
|
+
## 缓存迭代
|
125
|
+
|
126
|
+
`ArCache` 的缓存是以表为层级的,当触发缓存迭代后,这个表的全部缓存都会失效,导致一种类似缓存雪崩的情况,请特别注意。
|
127
|
+
下述的这些情况会导致缓存迭代:
|
128
|
+
|
129
|
+
- 表结构发生变化
|
130
|
+
- 激活/禁用 `ArCache`
|
131
|
+
- 使用 `ActiveRecord::Persistence::ClassMethods#upsert_all` 方法
|
132
|
+
|
133
|
+
## 注意事项
|
134
|
+
|
135
|
+
- `ArCache` 的缓存清除操作,是在事务提交或 `sql` 操作结束后开始的,这意味是可能出现脏读的(后续会尝试解决)。
|
136
|
+
- `ArCache` 缓存数据是完整的表行数据,因此当 `sql` 包含 `select` 字段,并且缓存缺失时,`ArCache` 会将其改成 `select *`,但最终实例化的对象依旧符合预期。
|
137
|
+
- 当使用跳过 `ActiveReord` 的回调方法,更新/删除数据时,`ArCache` 可能会多执行一条 `select primary_key` 的 `sql`,因为清除缓存需要 `primary_key` 数据。
|
138
|
+
|
139
|
+
## 警告
|
140
|
+
|
141
|
+
下述的这些情况都是严禁发生的行为,这些行为会导致 `ArCache` 的缓存正确性。
|
142
|
+
PS:`ActiveRecord` 使用者,不应该写出这些代码。
|
143
|
+
|
144
|
+
- 直接使用 `execute` 方法 更新/删除 数据。
|
145
|
+
- 直接使用比 `execute` 更底层方式,更新/删除 数据。
|
146
|
+
- 跳过 `ActiveRecord` 直接 更新/删除 数据。(后续会提供数据库触发器来解除这个限制)
|
147
|
+
|
148
|
+
如果这些行为无法避免的话,请按照上述[删除缓存](#用法)的方法,手动删除受影响的缓存数据,或者干脆直接禁止对应表的 `ArCache` 功能。
|
149
|
+
|
150
|
+
## 其它类似的库
|
151
|
+
|
152
|
+
这里还有一些其它的 `gem`,也提供了 `ActiveRecord` 的查询缓存功能。
|
153
|
+
|
154
|
+
- [identity_cache](https://github.com/Shopify/identity_cache)
|
155
|
+
- [second_level_cache](https://github.com/hooopo/second_level_cache)
|
156
|
+
- [cache-money](https://github.com/ngmoco/cache-money)
|
157
|
+
|
158
|
+
`ArCache` 跟他们存在一些下述的差异:
|
159
|
+
|
160
|
+
- `ArCache` 不依赖 `ActiveRecord` 的 `commit` 回调,所以你可以无所顾虑的直接使用跳过回调的方法。
|
161
|
+
- `ArCache` 的缓存是 `json` 序列化,不是 `Marshal` 序列化,所以缓存的使用是没有局限的。(仅当使用 `redis/memcached` 作为存储器时)
|
162
|
+
- `ArCache` 自动代理了标准的 `ActiveRecord` 实例化查询请求,所以不需要额外学习怎么使用缓存。
|
163
|
+
- `ArCache` 缓存是懒写入的,因此新创建的数据,不会直接写入缓存。
|
164
|
+
- `ArCache` 不会热更新缓存,因此数据被更新后,缓存就没有了。
|
165
|
+
- ...
|