Bug #18453
closedYJIT breaks Rails collection caching
Description
A minimal app that demonstrates this issue is available on GitHub. It has:
- One model,
Post
, with a stringtitle
attribute. - One controller action,
posts#index
, which fetchesPost
s in reverse order of creation into@posts
. - A root route to
posts#index
. - One view,
app/views/posts/index.html.erb
, which uses Rails collection rendering and caching as follows:
<ul>
<li><%= render partial: "posts/post", collection: @posts, cached: true %></li>
</ul>
- A partial,
app/views/posts/_post.html.erb
as follows:
<% cache post do %>
<li><%= post.title %></li>
<% end %>
I deployed this app to Heroku here. I configured it to use a Redis cache store.
I added 100 posts like so:
$ heroku run rails c
> 100.times do |i|
* Post.create! title: "Post ##{i + 1}"
* end
All requests to the app index, /
, show the posts in reverse chronological order as expected, with cold and warm cache:
* Post #100
* Post #99
* Post #98
* Post #97
* Post #96
* Post #95
...
I enabled YJIT by setting the RUBYOPT
environment variable to --yjit --yjit-exec-mem-size=32
and restarted the app server. I cleared the Redis cache with heroku run rails r 'Rails.cache.redis.flushall
.
The first request to /
with cold cache begins repeating Post #1 after #92:
* Post #100
* Post #99
* Post #98
* Post #97
* Post #96
* Post #95
* Post #94
* Post #93
* Post #92
* Post #1
* Post #1
* Post #1
* Post #1
* Post #1
* Post #1
...
All subsequent requests repeat Post #1 100 times:
* Post #1
* Post #1
* Post #1
* Post #1
* Post #1
* Post #1
* Post #1
* Post #1
* Post #1
...
On restart, Post #1 is repeated after #92 for the first request (as in the second-to-last example). Post #1 is repeated 100 times for subsequent requests (as in the last example).
Disabling YJIT and flushing the Redis cache restores the correct behavior.
Rails version: GitHub rails/rails
, 7-0-stable
branch, revision 499f12f6c03a4114eb649310e65200fe5d894db0