| 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. |