Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RecordNotFound error when using ActionMailer's deliver_later method #36

Open
cobalamin opened this issue Apr 9, 2015 · 9 comments
Open

Comments

@cobalamin
Copy link

I'm using ActionMailer to deliver mails on model creation. My controller code looks like this:

if @flaw.save
  render :show, status: :created

  FlawMailer.user_email(@flaw).deliver_later
  FlawMailer.reported_email(@flaw).deliver_later
else
...

I'm using deliver_later as I don't want the HTTP response by mailing concerns. However, this doesn't work and throws an error, apparently it's trying to use the obfuscated id to look up the Flaw model (even though I'm passing it as a parameter:

[ActiveJob] Enqueued ActionMailer::DeliveryJob (Job ID: 61049335-05ca-452e-8161-205b7c4bde72) to Inline(mailers) with arguments: "FlawMailer", "user_email", "deliver_now", gid://app/Flaw/18
[ActiveJob]   Flaw Load (0.3ms)  SELECT  "flaws".* FROM "flaws" WHERE "flaws"."id" = ?  ORDER BY created_at DESC LIMIT 1  [["id", 1928367482]]
Completed 500 Internal Server Error in 1596ms (Views: 26.2ms | ActiveRecord: 3.8ms)

ActiveRecord::RecordNotFound (Couldn't find Flaw with 'id'=1928367482):
  app/controllers/flaws_controller.rb:19:in `create'

When I use deliver_now instead, this problem vanishes. So there seems to be some incompatibilities between this gem and ActionMailer's deliver_later method.

@cobalamin
Copy link
Author

I've tracked down the problem. It lies in your reimplementation of the find method on obfuscated models.

ActionMailer's deliver_later will internally serialize the object to a globalid, which is then located again in the lines 139-141 of locator.rb.

gid.model_class.find gid.model_id, for a class Model and an ID 1, essentially boils down to Model.find 1. The :no_obfuscated_id option is rather obviously not passed and thus the error occurs because it's trying to deobfuscate the ID 1.

Now well, what to do about this? I'm stumped.

@swaathi
Copy link

swaathi commented May 8, 2015

I ran into this, and I used find_by_id instead of find. Hope that helps.

@scottbullard
Copy link

@cobalamin I am having a similar issue but my process is the opposite as yours. I am using Resque to queue my background thumbnail worker - which then re-saves the object. It doesn't seem to matter whether I find the object via the obfuscated ID or using the actual object ID - the results are the same.

Simple background queue variation (plain id vs. obfuscated):

Resque.enqueue(DocumentWorker, doc.id, params[:key]) if doc.id

-or-

Resque.enqueue(DocumentWorker, doc.to_param, params[:key]) if doc.id

The worker:

class DocumentWorker
  @queue = :thumbnail_processor_queue

  # Process document thumbnails
  def self.perform(doc_id, key)
    puts "DocumentWorker: #{doc_id.inspect}"
    document = Document.find_by_id(doc_id)
    puts "found doc: #{document.inspect}"
    document.remote_file_url = "https://s3-#{CarrierWave::Uploader::Base.fog_credentials[:region]}"\
                            ".amazonaws.com/#{CarrierWave::Uploader::Base.fog_directory}/#{key}"

    document.processing_failed = false if document.file.recreate_versions!
    document.save!
  end
end

Note: when using the second worker Resque.enqueue example, I also had this corresponding change to the DocumentWorker line document = Document.find(doc_id).

The results:
Note that it does not matter the method of retrieval - the processing fails on the 'save' method on line 13 of the worker. In both cases documents were successfully retrieved and the image processing was completed. In the first example it's trying to save using the obfuscated id and in the other the ID value appears blank.

10:42:09 resque.1 | DocumentWorker: 103
10:42:09 resque.1 | found doc: #<Document id: 103, idea_id: 13, user_id: 1, name: "gif1 small", file: nil, original_filename: "wsm-test1.gif", content_type: "image/gif", processing_failed: true, created_at: "2015-05-08 17:42:08", updated_at: "2015-05-08 17:42:08", featured: false>
Class
    DocumentWorker 
Arguments

    --- 103
    ...

    --- idea_documents/13/wsm-test1.gif
    ...

Exception
    ActiveRecord::RecordNotFound
Error
    Couldn't find Document with 'id'=1663753569

    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/core.rb:155:in `find'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/obfuscate_id-0.2.0/lib/obfuscate_id.rb:31:in `find'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/carrierwave-0.10.0/lib/carrierwave/mount.rb:239:in `find_previous_model_for_file'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/carrierwave-0.10.0/lib/carrierwave/mount.rb:234:in `store_previous_model_for_file'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:432:in `block in make_lambda'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:164:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:164:in `block in halting'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `block in call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `each'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_update_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/callbacks.rb:310:in `_update_record'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/timestamp.rb:70:in `_update_record'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/persistence.rb:502:in `create_or_update'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/callbacks.rb:302:in `block in create_or_update'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_save_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/callbacks.rb:302:in `create_or_update'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/persistence.rb:142:in `save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/validations.rb:43:in `save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:291:in `block in save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:347:in `block in with_transaction_returning_status'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/transaction.rb:188:in `within_new_transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:220:in `transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:344:in `with_transaction_returning_status'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:291:in `save!'
    /Users/scottbullard/projects/venturedoor/app/workers/document_worker.rb:13:in `perform'
11:10:41 resque.1 | DocumentWorker: "8563643726"
11:10:41 resque.1 | found doc: #<Document id: 108, idea_id: 13, user_id: 1, name: "jpg1 large", file: nil, original_filename: "wsm-test2-600x.jpg", content_type: "image/jpeg", processing_failed: true, created_at: "2015-05-08 18:10:37", updated_at: "2015-05-08 18:10:37", featured: false>
Class
    DocumentWorker 
Arguments

    --- '8563643726'

    --- idea_documents/13/wsm-test2-600x.jpg
    ...

Exception
    ActiveRecord::RecordNotFound
Error
    Couldn't find Document with an out of range value for 'id'

    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/core.rb:159:in `rescue in find'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/core.rb:128:in `find'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/obfuscate_id-0.2.0/lib/obfuscate_id.rb:31:in `find'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/carrierwave-0.10.0/lib/carrierwave/mount.rb:239:in `find_previous_model_for_file'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/carrierwave-0.10.0/lib/carrierwave/mount.rb:234:in `store_previous_model_for_file'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:432:in `block in make_lambda'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:164:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:164:in `block in halting'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `block in call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `each'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:504:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_update_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/callbacks.rb:310:in `_update_record'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/timestamp.rb:70:in `_update_record'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/persistence.rb:502:in `create_or_update'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/callbacks.rb:302:in `block in create_or_update'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_save_callbacks'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/callbacks.rb:302:in `create_or_update'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/persistence.rb:142:in `save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/validations.rb:43:in `save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:291:in `block in save!'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:347:in `block in with_transaction_returning_status'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/transaction.rb:188:in `within_new_transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:220:in `transaction'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:344:in `with_transaction_returning_status'
    /Users/scottbullard/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/transactions.rb:291:in `save!'
    /Users/scottbullard/projects/venturedoor/app/workers/document_worker.rb:13:in `perform'

@scottbullard
Copy link

On closer inspection, it seems that maybe it's an issue with carriewave's 'store_previous_model_for_file' method.

@cobalamin
Copy link
Author

@swaathi I think it would help, but I can't change core Rails libraries...

I worked around this by transmitting the "real" ID to the mailing methods:

FlawMailer.user_email(@flaw.id)

and then having the mailing methods find the model themselves, through that passed ID. It's certainly just a workaround because it requires the mailing methods to fetch the model, increasing coupling, but at least it works.

@swaathi
Copy link

swaathi commented May 17, 2015

Hey @cobalamin You can always try to retrieve the original ID from the scattered ID. You can see it here, https://github.com/namick/obfuscate_id/blob/master/lib/obfuscate_id.rb#L11.

So, Obfuscate_id uses Scatter Swap to randomize the ID's. You can always retrieve the original ID or get the random ID using the Scatter Swap functions. This requires two things, one is the ID and the other is the "spin". You can calculate the spin using this function, https://github.com/namick/obfuscate_id/blob/master/lib/obfuscate_id.rb#L44. The spin is actually calculated from your model name. So just assign the variable name to your model (say, Comment, with the capital C!), and you can generate your spin. Hope this helps!

@chengguangnan
Copy link

You can customize the locator with globalid.

# config/initializer/global_id.rb
GlobalID::Locator.use Rails.application.railtie_name.remove("_application").dasherize do |gid|
  gid.model_class.find_by_id gid.model_id
end

@b264
Copy link

b264 commented May 23, 2015

"used find_by_id instead of find"
👍 @swaathi That worked for me

@sberkley
Copy link

👍 to @chengguangnan's solution. That got deliver_later and other ActiveJob tasks working for me. Unless/until such a fix happens automatically in the gem, that suggestion should be in the README.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants