Author Build Commit PR
Jeremy Daer 14653 3f888f4 n/a
Repo Branch
rails/rails main
Message
Ensure variants are loaded and processed synchronously just once (#56225) In particular, when using a primary-replica DB setup, where variants are created synchronously in a GET request, manually connecting to the writer. In this case, we might try to load the variant record we just created in the primary from the replica, not find it due to replication lag, then process it again (downloading the original preview and everything), and fail to insert it because it's already there. Even though we track and memoize the just created `@record` in `ActiveStorage::VariantWithRecord` when we call `processed`, we instatiate a new object when we call `ActiveStorage::Blob#variant`. If we only call this once that's fine, but when processing the variant via `GET /rails/active_storage/representations/redirect`, we call this twice: one when setting the representation and processing it, as ```ruby @representation = @blob.representation(params[:variation_key]).processed ``` and another one when calling `@representation.url` for the redirect, which calls `ActiveStorage::Preview#url`, which ultimately ends up calling `ActiveStorage::VariantWithRecord.processed` again, but over a new instance of `ActiveStorage::VariantWithRecord`. This checks whether the variant record exists (the one we just created in the previous call to `processed`), but does so against the replica, which is likely to not find it if there's any delay (as these calls are very close together). With this change, we make sure we reuse the variant instance we just calculated for the preview image.

/api

Reference documentation

/guides

In-depth tutorials