[ActiveJob] Add discard_on ActiveJob::DeserializationError to ActiveStorage::AnalyzeJob

I have a growing list of failed ActiveStorage::AnalyzeJob jobs that have all failed with

ActiveJob::DeserializationError: Error while trying to deserialize arguments: Couldn’t find ActiveStorage::Blob with ‘id’=XXXX

After poking around a bit, I discovered that this is a documented situation and expected behavior: Add Deserialization section on guides at ActiveJob Exception · rails/rails@5e2273f · GitHub.

However, I was looking at ActiveStorage::PurgeJob and noticed that it includes discard_on ActiveRecord::RecordNotFound.

My question is this: Is there a good reason that the AnalyzeJob doesn’t silently drop jobs that will never run even though PurgeJob does? And if there isn’t, would someone be willing to approve the feature assuming I made a PR for it?

Do you know why the AnalyzeJobs are failing to find their blobs? Are you deleting blobs immediately after creating them, or…?

We’re migrating off of Paperclip and while I appreciate their migration guide to move to ActiveStorage, it would require several hours of downtime for us which was an immediate non-starter. As a result, I ended up writing some very hacky code to keep our models on Paperclip while also creating the appropriate Blob and Attachment records in the DB so we can switch over to ActiveStorage seamlessly. I have a hunch that some of that hacky code is creating excess blobs in certain circumstances which is leading to a relatively large number of failed jobs.

In case you’re interested, our migration logic looks something like:

  1. Monkey patch Paperclip so it calls an extra function every time it tries to write a new asset

  2. In that extra function, call ActiveStorage::Blob.create_after_upload! and ActiveStorage::Attachment.create with some reasonable arguments.

  3. Write some rake tasks that resave all of our existing Paperclip attachments which will cause them to all get re-saved under ActiveStorage.

  4. Update our code to use ActiveStorage (has_attached_file → has_one_attached, etc.)