Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
7424d2fd
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
7424d2fd
编写于
4月 16, 2019
作者:
K
Kasper Timm Hansen
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'collection-cache-versioning'
Signed-off-by:
N
Kasper Timm Hansen
<
kaspth@gmail.com
>
上级
758ba117
4f2ac80d
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
93 addition
and
15 deletion
+93
-15
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+11
-0
activerecord/lib/active_record/integration.rb
activerecord/lib/active_record/integration.rb
+8
-0
activerecord/lib/active_record/relation.rb
activerecord/lib/active_record/relation.rb
+36
-15
activerecord/test/cases/collection_cache_key_test.rb
activerecord/test/cases/collection_cache_key_test.rb
+34
-0
railties/lib/rails/application/configuration.rb
railties/lib/rails/application/configuration.rb
+4
-0
未找到文件。
activerecord/CHANGELOG.md
浏览文件 @
7424d2fd
*
Add
`ActiveRecord::Relation#cache_version`
to support recyclable cache keys via
the versioned entries in
`ActiveSupport::Cache`
. This also means that
`ActiveRecord::Relation#cache_key`
will now return a stable key that does not
include the max timestamp or count any more.
NOTE: This feature is turned off by default, and `cache_key` will still return
cache keys with timestamps until you set `ActiveRecord::Base.collection_cache_versioning = true`.
That's the setting for all new apps on Rails 6.0+
*Lachlan Sylvester*
*
Fix dirty tracking for
`touch`
to track saved changes.
Fixes #33429.
...
...
activerecord/lib/active_record/integration.rb
浏览文件 @
7424d2fd
...
...
@@ -22,6 +22,14 @@ module Integration
#
# This is +true+, by default on Rails 5.2 and above.
class_attribute
:cache_versioning
,
instance_writer:
false
,
default:
false
##
# :singleton-method:
# Indicates whether to use a stable #cache_key method that is accompanied
# by a changing version in the #cache_version method on collections.
#
# This is +false+, by default until Rails 6.1.
class_attribute
:collection_cache_versioning
,
instance_writer:
false
,
default:
false
end
# Returns a +String+, which Action Pack uses for constructing a URL to this
...
...
activerecord/lib/active_record/relation.rb
浏览文件 @
7424d2fd
...
...
@@ -291,27 +291,23 @@ def many?
limit_value
?
records
.
many?
:
size
>
1
end
# Returns a cache key that can be used to identify the records fetched by
# this query. The cache key is built with a fingerprint of the sql query,
# the number of records matched by the query and a timestamp of the last
# updated record. When a new record comes to match the query, or any of
# the existing records is updated or deleted, the cache key changes.
# Returns a stable cache key that can be used to identify this query.
# The cache key is built with a fingerprint of the SQL query.
#
# Product.where("name like ?", "%Cosmic Encounter%").cache_key
#
# => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000
"
#
Product.where("name like ?", "%Cosmic Encounter%").cache_key
#
# => "products/query-1850ab3d302391b85b8693e941286659
"
#
# If
the collection is loaded, the method will iterate through the record
s
#
to generate the timestamp, otherwise it will trigger one SQL query like:
# If
ActiveRecord::Base.collection_cache_versioning is turned off, as it wa
s
#
in Rails 6.0 and earlier, the cache key will also include a version.
#
# SELECT COUNT(*), MAX("products"."updated_at") FROM "products" WHERE (name like '%Cosmic Encounter%')
# ActiveRecord::Base.collection_cache_versioning = false
# Product.where("name like ?", "%Cosmic Encounter%").cache_key
# # => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000"
#
# You can also pass a custom timestamp column to fetch the timestamp of the
# last updated record.
#
# Product.where("name like ?", "%Game%").cache_key(:last_reviewed_at)
#
# You can customize the strategy to generate the key on a per model basis
# overriding ActiveRecord::Base#collection_cache_key.
def
cache_key
(
timestamp_column
=
:updated_at
)
@cache_keys
||=
{}
@cache_keys
[
timestamp_column
]
||=
@klass
.
collection_cache_key
(
self
,
timestamp_column
)
...
...
@@ -321,6 +317,31 @@ def compute_cache_key(timestamp_column = :updated_at) # :nodoc:
query_signature
=
ActiveSupport
::
Digest
.
hexdigest
(
to_sql
)
key
=
"
#{
klass
.
model_name
.
cache_key
}
/query-
#{
query_signature
}
"
if
cache_version
(
timestamp_column
)
key
else
"
#{
key
}
-
#{
compute_cache_version
(
timestamp_column
)
}
"
end
end
# Returns a cache version that can be used together with the cache key to form
# a recyclable caching scheme. The cache version is built with the number of records
# matching the query, and the timestamp of the last updated record. When a new record
# comes to match the query, or any of the existing records is updated or deleted,
# the cache version changes.
#
# If the collection is loaded, the method will iterate through the records
# to generate the timestamp, otherwise it will trigger one SQL query like:
#
# SELECT COUNT(*), MAX("products"."updated_at") FROM "products" WHERE (name like '%Cosmic Encounter%')
def
cache_version
(
timestamp_column
=
:updated_at
)
if
collection_cache_versioning
@cache_versions
||=
{}
@cache_versions
[
timestamp_column
]
||=
compute_cache_version
(
timestamp_column
)
end
end
def
compute_cache_version
(
timestamp_column
)
# :nodoc:
if
loaded?
||
distinct_value
size
=
records
.
size
if
size
>
0
...
...
@@ -356,9 +377,9 @@ def compute_cache_key(timestamp_column = :updated_at) # :nodoc:
end
if
timestamp
"
#{
key
}
-
#{
size
}
-
#{
timestamp
.
utc
.
to_s
(
cache_timestamp_format
)
}
"
"
#{
size
}
-
#{
timestamp
.
utc
.
to_s
(
cache_timestamp_format
)
}
"
else
"
#{
key
}
-
#{
size
}
"
"
#{
size
}
"
end
end
...
...
activerecord/test/cases/collection_cache_key_test.rb
浏览文件 @
7424d2fd
...
...
@@ -171,5 +171,39 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase
assert_match
(
/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\z/
,
developers
.
cache_key
)
end
test
"cache_key should be stable when using collection_cache_versioning"
do
with_collection_cache_versioning
do
developers
=
Developer
.
where
(
salary:
100000
)
assert_match
(
/\Adevelopers\/query-(\h+)\z/
,
developers
.
cache_key
)
/\Adevelopers\/query-(\h+)\z/
=~
developers
.
cache_key
assert_equal
ActiveSupport
::
Digest
.
hexdigest
(
developers
.
to_sql
),
$1
end
end
test
"cache_version for relation"
do
with_collection_cache_versioning
do
developers
=
Developer
.
where
(
salary:
100000
).
order
(
updated_at: :desc
)
last_developer_timestamp
=
developers
.
first
.
updated_at
assert_match
(
/(\d+)-(\d+)\z/
,
developers
.
cache_version
)
/(\d+)-(\d+)\z/
=~
developers
.
cache_version
assert_equal
developers
.
count
.
to_s
,
$1
assert_equal
last_developer_timestamp
.
to_s
(
ActiveRecord
::
Base
.
cache_timestamp_format
),
$2
end
end
def
with_collection_cache_versioning
(
value
=
true
)
@old_collection_cache_versioning
=
ActiveRecord
::
Base
.
collection_cache_versioning
ActiveRecord
::
Base
.
collection_cache_versioning
=
value
yield
ensure
ActiveRecord
::
Base
.
collection_cache_versioning
=
@old_collection_cache_versioning
end
end
end
railties/lib/rails/application/configuration.rb
浏览文件 @
7424d2fd
...
...
@@ -142,6 +142,10 @@ def load_defaults(target_version)
active_storage
.
queues
.
analysis
=
:active_storage_analysis
active_storage
.
queues
.
purge
=
:active_storage_purge
end
if
respond_to?
(
:active_record
)
active_record
.
collection_cache_versioning
=
true
end
else
raise
"Unknown version
#{
target_version
.
to_s
.
inspect
}
"
end
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录