I am trying to test the sending on an email by DelayedJob using cucumber. The feature actually works in the browser (in both development and production environments) but I'm running into a weird SQlite3 exception when I try to test it.
The test log is at the bottom. As you can see, it fails with an SQLite3::SQLException just after inserting the email sending job into the queue.
According to Delayed::Job the reason for the failure is:
Delayed::DeserializationError
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/psych_ext.rb:108:in `rescue in visit_Psych_Nodes_Mapping_with_class'
Anyone got any idea what is happening here?
I found a related question but the problem there doesn't appear to be constrained to the test environment. Thus I don't think the solution will be the same.
SQLite3 Error - cannot rollback - no transaction is active
Here's the full test trace:
SQL (82.7ms) INSERT INTO "delayed_jobs" ("attempts", "created_at", "failed_at", "handler", "last_error", "locked_at", "locked_by", "priority", "queue", "run_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["attempts", 0], ["created_at", Tue, 08 May 2012 12:14:15 UTC +00:00], ["failed_at", nil], ["handler", "--- !ruby/object:Delayed::PerformableMailer\nobject: !ruby/class 'InvitationMailer'\nmethod_name: :invite\nargs:\n- !ruby/ActiveRecord:Invitation\n attributes:\n id: 1\n sender_id: 1\n search_id: 1\n token: 4cba1a8a36de826493b1d8a8cc21091e2fb393e1\n sent_at: \n recipient_email: peter#example.com\n created_at: 2012-05-08 12:14:15.702071000 Z\n updated_at: 2012-05-08 12:14:15.702071000 Z\n recipient_id: \n accepted: \n"], ["last_error", nil], ["locked_at", nil], ["locked_by", nil], ["priority", 0], ["queue", nil], ["run_at", Tue, 08 May 2012 12:14:15 UTC +00:00], ["updated_at", Tue, 08 May 2012 12:14:15 UTC +00:00]]
(0.9ms) commit transaction
SQLite3::SQLException: cannot commit - no transaction is active: commit transaction
(0.5ms) rollback transaction
SQLite3::SQLException: cannot rollback - no transaction is active: rollback transaction
Completed 500 Internal Server Error in 126ms
SQL (1.9ms) UPDATE "delayed_jobs" SET locked_at = '2012-05-08 12:14:16.993126', locked_by = 'host:dtmbp.local pid:14059' WHERE (id = 3 and (locked_at is null or locked_at < '2012-05-08 08:14:16.993126') and (run_at <= '2012-05-08 12:14:16.993126'))
Invitation Load (0.2ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = ? LIMIT 1 [["id", 1]]
Invitation Load (0.1ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = ? LIMIT 1 [["id", 1]]
Invitation Load (0.1ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = ? LIMIT 1 [["id", 1]]
Invitation Load (0.1ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = ? LIMIT 1 [["id", 1]]
Invitation Load (0.1ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = ? LIMIT 1 [["id", 1]]
(0.1ms) begin transaction
(0.5ms) UPDATE "delayed_jobs" SET "locked_at" = '2012-05-08 12:14:16.993126', "locked_by" = 'host:dtmbp.local pid:14059', "last_error" = '{Delayed::DeserializationError
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/psych_ext.rb:108:in `rescue in visit_Psych_Nodes_Mapping_with_class''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/psych_ext.rb:101:in `visit_Psych_Nodes_Mapping_with_class''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:15:in `visit''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:5:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:20:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:134:in `block in visit_Psych_Nodes_Sequence''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:134:in `each''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:134:in `visit_Psych_Nodes_Sequence''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:15:in `visit''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:5:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:20:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:276:in `block in revive''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:276:in `map''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:276:in `revive''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:219:in `visit_Psych_Nodes_Mapping''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/psych_ext.rb:119:in `visit_Psych_Nodes_Mapping_with_class''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:15:in `visit''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:5:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:20:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:231:in `visit_Psych_Nodes_Document''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:15:in `visit''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/visitor.rb:5:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:20:in `accept''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych/nodes/node.rb:35:in `to_ruby''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/psych.rb:128:in `load''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/backend/base.rb:84:in `payload_object''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/backend/base.rb:94:in `block in invoke_job''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `block in initialize''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `execute''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:38:in `run_callbacks''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/backend/base.rb:91:in `invoke_job''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:178:in `block (2 levels) in run''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/timeout.rb:68:in `timeout''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:178:in `block in run''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/benchmark.rb:295:in `realtime''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:177:in `run''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:234:in `block in reserve_and_run_one_job''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `block in initialize''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `execute''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:38:in `run_callbacks''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:234:in `reserve_and_run_one_job''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:162:in `block in work_off''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:161:in `times''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:161:in `work_off''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:133:in `block (4 levels) in start''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/benchmark.rb:295:in `realtime''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:132:in `block (3 levels) in start''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `block in initialize''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `execute''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:38:in `run_callbacks''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:129:in `block (2 levels) in start''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:128:in `loop''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:128:in `block in start''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/plugins/clear_locks.rb:7:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/plugins/clear_locks.rb:7:in `block (2 levels) in <class:ClearLocks>''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:78:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:78:in `block (2 levels) in add''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `block in initialize''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:78:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:78:in `block in add''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `execute''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:38:in `run_callbacks''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:127:in `start''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/tasks.rb:9:in `block (2 levels) in <top (required)>''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `call''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `block in execute''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `each''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `execute''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/task.rb:158:in `block in invoke_with_call_chain''
/Users/davidtuite/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/task.rb:151:in `invoke_with_call_chain''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/task.rb:144:in `invoke''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:116:in `invoke_task''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block (2 levels) in top_level''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `each''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block in top_level''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:88:in `top_level''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:66:in `block in run''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/lib/rake/application.rb:63:in `run''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194#global/gems/rake-0.9.2.2/bin/rake:33:in `<top (required)>''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/bin/rake:19:in `load''
/Users/davidtuite/.rvm/gems/ruby-1.9.3-p194/bin/rake:19:in `<main>''', "failed_at" = '2012-05-08 12:14:17.131476', "updated_at" = '2012-05-08 12:14:17.132975' WHERE "delayed_jobs"."id" = 3
(1.5ms) commit transaction
I just had this error and realized that the AR object in question had simply already been deleted. Maybe that's your situation too?
Related link: psych_ext.rb#L101 breaks restoring of deleted serialized objects
Related
I started to learn Ruby on Rails and I am facing a problem with command logs.
I am starting my server with Command Prompt.
My Ruby version is: 2.7
My Rails version is: 7.0
I want to turn off or hide unnecessary logs.
Logs example:
Post Load (0.5ms) SELECT "posts".* FROM "posts" WHERE "posts"."author_id" = $1 ORDER BY "posts"."created_at" DESC LIMIT $2 [["author_id", 3], ["LIMIT", 3]]
Could not log "sql.active_record" event. Encoding::CompatibilityError: incompatible encoding regexp match (ASCII-8BIT regexp with UTF-8 string) [
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-7.0.4/lib/active_support/backtrace_cleaner.rb:96:in `sub'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-7.0.4/lib/active_support/backtrace_cleaner.rb:96:in `block in add_gem_filter'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-7.0.4/lib/active_support/backtrace_cleaner.rb:109:in `block (2 levels) in filter_backtrace'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:144:in `each'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:144:in `each'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:144:in `each'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:144:in `each'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:144:in `first'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:144:in `extract_query_source_location'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:136:in `log_query_source'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:131:in `debug'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/log_subscriber.rb:71:in `sql'",
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-
I tried to find solution online, but I didn't find anything that will help me.
I am using a delayed job on a Rails 5 project with the 'delayed_job_active_record' gem.
I can't figure out how to check on the status of the job.
I managed to get delayed job to run. The jobs are failing due to an issue with processing uploaded files (that's another issue).
In my controller:
def create
#upload = Upload.create(status: "in progress")
#upload.delay.create_ln(lecture_note_params, current_user, #upload.id)
render json: {"status": #upload.status, "id": #upload.id}, status: 200
end
Here's my model code for the upload model:
class Upload < ApplicationRecord
def create_ln(lecture_note_params, current_user, upload_id)
#lecture_note = LectureNote.new(lecture_note_params.merge(user: current_user))
#lecture_note.upload_id = upload_id
if #lecture_note.save
#nothing
else
logger.info #lecture_note.errors.full_messages.to_sentence
#upload.update(error: #lecture_note.errors.full_messages.to_sentence, status: "error")
end
end
end
The lecture notes don't save. They fail for the reason mentioned above. I need the upload model to update with the error status. How can I do that?
I can see the delayed job in the console :
irb(main):002:0> ap Delayed::Job.last
D, [2019-12-12T06:12:08.014249 #4] DEBUG -- : Delayed::Backend::ActiveRecord::Job Load (6.3ms) SELECT `delayed_jobs`.* FROM `delayed_jobs` ORDER BY `delayed_jobs`.`id` DESC LIMIT 1
#<Delayed::Backend::ActiveRecord::Job:0x0000561edb710f70> {
:id => 16,
:priority => 0,
:attempts => 1,
:handler => "### ALL KINDS OF STUFF - REDACTED ###",
:run_at => Thu, 12 Dec 2019 06:10:32 UTC +00:00,
:locked_at => nil,
:failed_at => Thu, 12 Dec 2019 06:11:17 UTC +00:00,
:locked_by => nil,
:queue => nil,
:created_at => Thu, 12 Dec 2019 06:10:32 UTC +00:00,
:updated_at => Thu, 12 Dec 2019 06:11:17 UTC +00:00
}
After the job fails, the "failed_at" field is updated. How can I access that and update my upload model?
Here is the log file while a file is uploading:
D, [2019-12-12T06:11:17.846638 #4] DEBUG -- : Upload Load (1.1ms) SELECT `uploads`.* FROM `uploads` WHERE `uploads`.`id` = 31 LIMIT 1
D, [2019-12-12T06:11:17.852741 #4] DEBUG -- : User Load (1.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
[Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Job Upload#create_ln (id=16) RUNNING
I, [2019-12-12T06:11:17.853180 #4] INFO -- : 2019-12-12T06:11:17+0000: [Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Job Upload#create_ln (id=16) RUNNING
D, [2019-12-12T06:11:17.855002 #4] DEBUG -- : (1.2ms) BEGIN
I, [2019-12-12T06:11:17.855200 #4] INFO -- : pdf to html running..............
I, [2019-12-12T06:11:17.855268 #4] INFO -- : step 0 ..............
I, [2019-12-12T06:11:17.855326 #4] INFO -- : step 1 ..............
I, [2019-12-12T06:11:17.855388 #4] INFO -- : step 2 ..............
D, [2019-12-12T06:11:17.856673 #4] DEBUG -- : (1.1ms) ROLLBACK
[Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Job Upload#create_ln (id=16) FAILED (0 prior attempts) with IOError: uninitialized stream
E, [2019-12-12T06:11:17.857261 #4] ERROR -- : 2019-12-12T06:11:17+0000: [Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Job Upload#create_ln (id=16) FAILED (0 prior attempts) with IOError: uninitialized stream
[Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Job Upload#create_ln (id=16) FAILED permanently because of 1 consecutive failures
E, [2019-12-12T06:11:17.857416 #4] ERROR -- : 2019-12-12T06:11:17+0000: [Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Job Upload#create_ln (id=16) FAILED permanently because of 1 consecutive failures
D, [2019-12-12T06:11:17.858576 #4] DEBUG -- : (0.9ms) BEGIN
D, [2019-12-12T06:11:17.861961 #4] DEBUG -- : SQL (1.6ms) UPDATE `delayed_jobs` SET `last_error` = 'uninitialized stream\n/app/vendor/ruby-2.6.3/lib/ruby/2.6.0/tempfile.rb:221:in `path\'\n/app/vendor/ruby-2.6.3/lib/ruby/2.6.0/tempfile.rb:221:in `path\'\n/app/app/models/lecture_note.rb:60:in `pdf_to_html\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:382:in `block in make_lambda\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:150:in `block (2 levels) in halting_and_conditional\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:770:in `block (2 levels) in deprecated_false_terminator\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:769:in `catch\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:769:in `block in deprecated_false_terminator\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:151:in `block in halting_and_conditional\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:454:in `block in call\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:454:in `each\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:454:in `call\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:101:in `__run_callbacks__\'\n/app/vendor/bundle/ruby/2.6.0/gems/activesupport-5.0.7.1/lib/active_support/callbacks.rb:750:in `_run_validation_callbacks\'\n/app/vendor/bundle/ruby/2.6.0/gems/activemodel-5.0.7.1/lib/active_model/validations/callbacks.rb:113:in `run_validations!\'\n/app/vendor/bundle/ruby/2.6.0/gems/activemodel-5.0.7.1/lib/active_model/validations.rb:338:in `valid?\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/validations.rb:65:in `valid?\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/validations.rb:82:in `perform_validations\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/validations.rb:44:in `save\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/attribute_methods/dirty.rb:22:in `save\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/transactions.rb:319:in `block (2 levels) in save\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/transactions.rb:395:in `block in with_transaction_returning_status\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/connection_adapters/abstract/database_statements.rb:232:in `block in transaction\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/connection_adapters/abstract/transaction.rb:189:in `within_new_transaction\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/connection_adapters/abstract/database_statements.rb:232:in `transaction\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/transactions.rb:211:in `transaction\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/transactions.rb:392:in `with_transaction_returning_status\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/transactions.rb:319:in `block in save\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/transactions.rb:334:in `rollback_active_record_state!\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/transactions.rb:318:in `save\'\n/app/vendor/bundle/ruby/2.6.0/gems/activerecord-5.0.7.1/lib/active_record/suppressor.rb:41:in `save\'\n/app/app/models/upload.rb:7:in `create_ln\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/performable_method.rb:26:in `perform\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/backend/base.rb:81:in `block in invoke_job\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:61:in `block in initialize\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:66:in `execute\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:40:in `run_callbacks\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/backend/base.rb:78:in `invoke_job\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:230:in `block (2 levels) in run\'\n/app/vendor/ruby-2.6.3/lib/ruby/2.6.0/timeout.rb:93:in `block in timeout\'\n/app/vendor/ruby-2.6.3/lib/ruby/2.6.0/timeout.rb:103:in `timeout\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:230:in `block in run\'\n/app/vendor/ruby-2.6.3/lib/ruby/2.6.0/benchmark.rb:308:in `realtime\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:229:in `run\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:312:in `block in reserve_and_run_one_job\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:61:in `block in initialize\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:66:in `execute\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:40:in `run_callbacks\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:312:in `reserve_and_run_one_job\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:213:in `block in work_off\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:212:in `times\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:212:in `work_off\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:175:in `block (4 levels) in start\'\n/app/vendor/ruby-2.6.3/lib/ruby/2.6.0/benchmark.rb:308:in `realtime\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:174:in `block (3 levels) in start\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:61:in `block in initialize\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:66:in `execute\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:40:in `run_callbacks\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:173:in `block (2 levels) in start\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:172:in `loop\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:172:in `block in start\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/plugins/clear_locks.rb:7:in `block (2 levels) in <class:ClearLocks>\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:79:in `block (2 levels) in add\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:61:in `block in initialize\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:79:in `block in add\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:66:in `execute\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/lifecycle.rb:40:in `run_callbacks\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/worker.rb:171:in `start\'\n/app/vendor/bundle/ruby/2.6.0/gems/delayed_job-4.1.8/lib/delayed/tasks.rb:9:in `block (2 levels) in <top (required)>\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/task.rb:273:in `block in execute\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/task.rb:273:in `each\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/task.rb:273:in `execute\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/task.rb:214:in `block in invoke_with_call_chain\'\n/app/vendor/ruby-2.6.3/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/task.rb:194:in `invoke_with_call_chain\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/task.rb:183:in `invoke\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:160:in `invoke_task\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:116:in `block (2 levels) in top_level\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:116:in `each\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:116:in `block in top_level\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:125:in `run_with_threads\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:110:in `top_level\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:83:in `block in run\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:186:in `standard_exception_handling\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/lib/rake/application.rb:80:in `run\'\n/app/vendor/bundle/ruby/2.6.0/gems/rake-12.3.3/exe/rake:27:in `<top (required)>\'\n/app/vendor/bundle/ruby/2.6.0/bin/rake:23:in `load\'\n/app/vendor/bundle/ruby/2.6.0/bin/rake:23:in `<top (required)>\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/cli/exec.rb:74:in `load\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/cli/exec.rb:74:in `kernel_load\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/cli/exec.rb:28:in `run\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/cli.rb:463:in `exec\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/cli.rb:27:in `dispatch\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/cli.rb:18:in `start\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/exe/bundle:30:in `block in <top (required)>\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors\'\n/app/vendor/bundle/ruby/2.6.0/gems/bundler-1.17.3/exe/bundle:22:in `<top (required)>\'\n/app/bin/bundle:3:in `load\'\n/app/bin/bundle:3:in `<main>\'', `attempts` = 1, `failed_at` = '2019-12-12 06:11:17', `updated_at` = '2019-12-12 06:11:17' WHERE `delayed_jobs`.`id` = 16
D, [2019-12-12T06:11:17.867680 #4] DEBUG -- : (5.1ms) COMMIT
D, [2019-12-12T06:11:17.870699 #4] DEBUG -- : SQL (1.8ms) UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_at` = '2019-12-12 06:11:17', `delayed_jobs`.`locked_by` = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4' WHERE ((run_at <= '2019-12-12 06:11:17.867786' AND (locked_at IS NULL OR locked_at < '2019-12-12 02:11:17.867819') OR locked_by = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1
[Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] 8 jobs processed at 13.8130 j/s, 8 failed
I, [2019-12-12T06:11:17.870885 #4] INFO -- : 2019-12-12T06:11:17+0000: [Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] 8 jobs processed at 13.8130 j/s, 8 failed
D, [2019-12-12T06:11:17.873258 #4] DEBUG -- : SQL (1.2ms) UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_at` = '2019-12-12 06:11:17', `delayed_jobs`.`locked_by` = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4' WHERE ((run_at <= '2019-12-12 06:11:17.870973' AND (locked_at IS NULL OR locked_at < '2019-12-12 02:11:17.871010') OR locked_by = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1
D, [2019-12-12T06:11:22.878755 #4] DEBUG -- : SQL (1.5ms) UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_at` = '2019-12-12 06:11:22', `delayed_jobs`.`locked_by` = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4' WHERE ((run_at <= '2019-12-12 06:11:22.876103' AND (locked_at IS NULL OR locked_at < '2019-12-12 02:11:22.876164') OR locked_by = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1
D, [2019-12-12T06:11:27.882776 #4] DEBUG -- : SQL (1.6ms) UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_at` = '2019-12-12 06:11:27', `delayed_jobs`.`locked_by` = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4' WHERE ((run_at <= '2019-12-12 06:11:27.880101' AND (locked_at IS NULL OR locked_at < '2019-12-12 02:11:27.880160') OR locked_by = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1
D, [2019-12-12T06:11:32.890712 #4] DEBUG -- : SQL (1.6ms) UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_at` = '2019-12-12 06:11:32', `delayed_jobs`.`locked_by` = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4' WHERE ((run_at <= '2019-12-12 06:11:32.887163' AND (locked_at IS NULL OR locked_at < '2019-12-12 02:11:32.887243') OR locked_by = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1
D, [2019-12-12T06:11:37.894751 #4] DEBUG -- : SQL (1.5ms) UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_at` = '2019-12-12 06:11:37', `delayed_jobs`.`locked_by` = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4' WHERE ((run_at <= '2019-12-12 06:11:37.892094' AND (locked_at IS NULL OR locked_at < '2019-12-12 02:11:37.892153') OR locked_by = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1
^C[Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Exiting...
I, [2019-12-12T06:11:39.976787 #4] INFO -- : 2019-12-12T06:11:39+0000: [Worker(host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4)] Exiting...
D, [2019-12-12T06:11:42.902214 #4] DEBUG -- : SQL (5.4ms) UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_by` = NULL, `delayed_jobs`.`locked_at` = NULL WHERE `delayed_jobs`.`locked_by` = 'host:575e618d-28f3-49a1-8545-88afa11b60d1 pid:4'
OK I found the solution. Tun's answer pointed me in the general direction (very general direction) but led me to it.
delayed_job has callbacks but I didn't know where to put them, or how to use them. They simply go in the model where the job method takes place. That wasn't obvious in the available documentation (to me anyway).
I was looking at this the wrong way. I already have the upload class to manage the creation of the lecture notes. So using the callbacks I can have the job update the class with the status. That's what we needed in the end.
The def failure(job) method did the trick!
I don't 100% understand how these callbacks actually work behind the scenes but they do work.
class Upload < ApplicationRecord
def create_ln(lecture_note_params, current_user, upload_id)
#lecture_note = LectureNote.new(lecture_note_params.merge(user: current_user))
#lecture_note.upload_id = upload_id
# if #lecture_note.save
# #nothing
# else
# logger.info #lecture_note.errors.full_messages.to_sentence
# #upload.update(error: #lecture_note.errors.full_messages.to_sentence, status: "error")
# end
begin
#lecture_note.save
rescue Exception => e
puts #lecture_note.errors.full_messages.to_sentence
self.update(error: #lecture_note.errors.full_messages.to_sentence, status: "error")
end
end
def success(job)
puts "Job complete ------->"
end
def error(job, exception)
puts "Job failed ERROR ------->"
puts #lecture_note.errors.full_messages.to_sentence
self.update(error: #lecture_note.errors.full_messages.to_sentence, status: "error")
end
# def after(job)
# # Do something useful here
# end
def failure(job)
puts "Job failed FAILURE ------->"
puts #lecture_note.errors.full_messages.to_sentence
self.update(error: #lecture_note.errors.full_messages.to_sentence, status: "error")
end
end
Generally, we should not check the job. The job should report back. (Observer pattern - I think)
I usually do one or combination of the followings
ActionCable to inform progress of the job (exception in your case)
Catch Exception in the job and update Upload with status
Use third party gem (such as activity_notification for notification.
DelayedJob proposed Global Hooks but I think it is not implemented yet.
I have a very basic table called radio_inventories
create_table "radio_inventories", id: false, force: true do |t|
t.integer "radio_id"
t.string "location"
t.string "distributor"
t.string "radio_user"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "radio_inventories", ["radio_id"], name:
"index_radio_inventories_on_radio_id"
Along with a very simple model:
class RadioInventory < ActiveRecord::Base
self.table_name = 'radio_inventories'
end
For some reason when I use the rails console to create new instances of these models and save them, it saves just fine
irb(main):001:0> x = RadioInventory.new
=> #<RadioInventory radio_id: nil, location: nil, distributor: nil, radio_user: nil, created_at: nil, updated_at: nil>
irb(main):002:0> x.radio_id = 123
=> 123
irb(main):003:0> x.save
(0.0ms) begin transaction
SQL (1.0ms) INSERT INTO "radio_inventories" ("created_at", "radio_id", "updated_at") VALUES (?, ?, ?) [["created_at", "2016-10-18 02:31:26.487353"], ["radio_id", 123], ["updated_at", "2016-10-18 02:31:26.487353"]]
(41.0ms) commit transaction
=> true
But when I then try to update the record I get an error. This happens when I use .save, .update, or .update_attributes.
irb(main):004:0> x = RadioInventory.first
RadioInventory Load (0.0ms) SELECT "radio_inventories".* FROM "radio_inventories" LIMIT 1
=> #<RadioInventory radio_id: 8565, location: nil, distributor: nil, radio_user: nil, created_at: "2016-10-18 02:22:59", updated_at: "2016-10-18 02:22:59">
irb(main):005:0> x.location = 'IT'
=> "IT"
irb(main):006:0> x.save
(0.0ms) begin transaction
(0.0ms) rollback transaction
TypeError: nil is not a symbol
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activemodel-4.1.8/lib/active_model/dirty.rb:162:in `attribute_was'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/attribute_methods/primary_key.rb:44:in `id_was'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/persistence.rb:494:in `_update_record'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/locking/optimistic.rb:70:in `_update_record'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/attribute_methods/dirty.rb:83:in `_update_record'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/callbacks.rb:310:in `block in _update_record'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activesupport-4.1.8/lib/active_support/callbacks.rb:82:in `run_callbacks'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/callbacks.rb:310:in `_update_record'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/timestamp.rb:70:in `_update_record'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/persistence.rb:483:in `create_or_update'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/callbacks.rb:302:in `block in create_or_update'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activesupport-4.1.8/lib/active_support/callbacks.rb:82:in `run_callbacks'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/callbacks.rb:302:in `create_or_update'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/persistence.rb:103:in `save'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/validations.rb:51:in `save'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/attribute_methods/dirty.rb:21:in `save'
... 2 levels...
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `block in transaction'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `within_new_transaction'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `transaction'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/transactions.rb:208:in `transaction'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/transactions.rb:268:in `block in save'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/transactions.rb:283:in `rollback_active_record_state!'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.1.8/lib/active_record/transactions.rb:267:in `save'
from (irb):6
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.1.8/lib/rails/commands/console.rb:90:in `start'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.1.8/lib/rails/commands/console.rb:9:in `start'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:69:in `console'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.1.8/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'irb(main):007:0>
I've also this with models/tables named "RadioStatus/radio_statuses" which also failed. But when I try with the model/table named 'RadioTracker/radio_trackers', everything works fine and as expected.
Any insight on why ActiveRecord behaves this way would be greatly appreciated.
When there is no default primary id for a table, Rails throws this error when we try to update a ActiveRecord object. so you can try putting self.primary_key = 'radio_id' at the beginning of RadioInventory model class.
And I see that in your migration there is id: false so I guess this is the problem.
You should do assign value on update_attributes:
x= RadioInventory.first
x.update_attributes(location: 'IT')
ActiveRecord 4.1.1 is generating some peculiar SQL on save that postgres is choking on:
SELECT "projects".* FROM "projects" WHERE ('uid') LIMIT 1
PG::InvalidTextRepresentation: ERROR: invalid input syntax for type boolean: "uid"
I'm pretty sure that the "boolean" being referred to here is actually the WHERE() syntax which is expecting a boolean expression as an argument.
uid is defined as the primary key on my model (see below)... but why is it just saying WHERE('uid') when it's doing select_all (see stacktrace)? (and why is it doing select_all on save?)
Rails Console
p = Project.new(name: "test", description: "test", workflow_id: 1)
=> #<Project name: "test", description: "test", user_id: nil, uid: nil, created_at: nil, updated_at: nil, workflow_id: 1, active: nil>
irb(main):031:0> p.save
(1.9ms) BEGIN
Project Load (5.5ms) SELECT "projects".* FROM "projects" WHERE ('uid') LIMIT 1
PG::InvalidTextRepresentation: ERROR: invalid input syntax for type boolean: "uid"
LINE 1: SELECT "projects".* FROM "projects" WHERE ('uid') LIMIT 1
^
: SELECT "projects".* FROM "projects" WHERE ('uid') LIMIT 1
(1.7ms) ROLLBACK
ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type boolean: "uid"
LINE 1: SELECT "projects".* FROM "projects" WHERE ('uid') LIMIT 1
^
: SELECT "projects".* FROM "projects" WHERE ('uid') LIMIT 1
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/postgresql_adapter.rb:815:in `async_exec'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/postgresql_adapter.rb:815:in `block in exec_no_cache'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract_adapter.rb:373:in `block in log'
from /app/vendor/bundle/ruby/2.0.0/gems/activesupport-4.1.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract_adapter.rb:367:in `log'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/postgresql_adapter.rb:815:in `exec_no_cache'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/postgresql_adapter.rb:947:in `select'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract/database_statements.rb:31:in `select_all'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract/query_cache.rb:69:in `select_all'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/querying.rb:39:in `find_by_sql'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/relation.rb:603:in `exec_queries'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/relation.rb:487:in `load'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/relation.rb:231:in `to_a'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/relation/finder_methods.rb:451:in `find_take'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/relation/finder_methods.rb:98:in `take'
... 41 levels...
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `block in transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract/database_statements.rb:219:in `within_new_transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/transactions.rb:208:in `transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/transactions.rb:268:in `block in save'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/transactions.rb:283:in `rollback_active_record_state!'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.1/lib/active_record/transactions.rb:267:in `save'
from (irb):31
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.1.1/lib/rails/commands/console.rb:90:in `start'
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.1.1/lib/rails/commands/console.rb:9:in `start'
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.1.1/lib/rails/commands/commands_tasks.rb:69:in `console'
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.1.1/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.1.1/lib/rails/commands.rb:17:in `<top (required)>'
from /app/bin/rails:4:in `require'
from /app/bin/rails:4:in `<main>
Model
class Project < ActiveRecord::Base
self.primary_key = "uid"
end
ActiveRecord mixin for generating IDs
module ActiveRecordUIDExtension
extend ActiveSupport::Concern
def generate_uid
return unless self.class.column_names.include?("uid")
self.id = SecureRandom.random_number(36**10).to_s(36)
while !self.class.find_by(:uid, self.id).nil? do
self.id = SecureRandom.random_number(36**10).to_s(36)
end
end
end
ActiveRecord::Base.send(:include, ActiveRecordUIDExtension)
ActiveRecord::Base.send(:before_create, :generate_uid)
Gemfile.lock
activerecord (4.1.1)
activemodel (= 4.1.1)
activesupport (= 4.1.1)
arel (~> 5.0.0)
Your mixin doesn't make any sense. This part right here is causing the bad SQL:
self.class.find_by(:uid, self.id)
That's producing invalid SQL because you're telling it to. find_by has a flexible interface so it has to do some parsing to see how you're calling it. When you say:
find_by(a, b)
the argument parsing probably assumes that you're trying to use this form:
find_by('some_sql_snippet', placeholder_valid)
as in this example from the docs:
find_by("published_at < ?", 2.weeks.ago)
Then it will probably to_s the first argument and scan it for placeholders. When you say:
find_by(:uid, self.id)
you'll end up with :uid.to_s and self.id will be ignored because there aren't placeholders in that string. That would explain why you're seeing where ('uid') in the SQL.
Fix your mixin to make sense:
self.class.find_by(:uid => self.id)
or better, switch to exists? to avoid building a whole model instance just to see if there's a row in the database:
self.class.where(:uid => self.id).exists?
self.class.exists?(:uid => self.id)
I use find_by_sql and within a second it gives me back a response:
Report.find_by_sql("SELECT min(reports.time) FROM reports WHERE unit_id = '#{Unit.find(3007).id}' AND driver_id = '#{Driver.find(2).id}' AND time >= '#{beginning}' AND time <= '#{ending}'")
Unit Load (111.1ms) SELECT "units".* FROM "units" WHERE "units"."id" = $1 LIMIT 1 [["id", 3007]]
Driver Load (98.0ms) SELECT "drivers".* FROM "drivers" WHERE "drivers"."id" = $1 LIMIT 1 [["id", 2]]
Report Load (59.6ms) SELECT min(reports.time) FROM reports WHERE unit_id = '3007' AND driver_id = '2' AND time >= '2013-03-01 00:00:00 UTC
' AND time <= '2013-03-31 23:59:59 UTC'
=> [#<Report >]
Then I try to use a scope with activerecord relation methods to build the same query:
scope :start_driver_time, lambda { |unit, driver, start_time, end_time|
where("unit_id = ? AND
driver_id = ? AND
time >= ? AND
time <= ?",
unit.id, driver.id, start_time, end_time)
.order("time asc")
.minimum(:time)
}
1.9.3p0 :012 > Report.start_driver_time(Unit.find(3007), Driver.find(2), beginning, ending)
Unit Load (48.4ms) SELECT "units".* FROM "units" WHERE "units"."id" = $1 LIMIT 1 [["id", 3007]]
Driver Load (46.5ms) SELECT "drivers".* FROM "drivers" WHERE "drivers"."id" = $1 LIMIT 1 [["id", 2]]
(49.3ms) SELECT MIN("reports"."time") AS min_id FROM "reports" WHERE (unit_id = 3007 AND
driver_id = 2 AND
time >= '2013-03-01 00:00:00.000000' AND
time <= '2013-03-31 23:59:59.999999')
But after 45 minutes the query is still running.
When I press control + c this is the output:
^C Report Load (30484.0ms) SELECT "reports".* FROM "reports"
ActiveRecord::StatementInvalid: IRB::Abort: abort then interrupt!: SELECT "reports".* FROM "reports"
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:88:in `irb_abort'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:257:in `signal_handle'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:65:in `block in start'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:1151:in `call'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:1151:in `async_exec'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:1151:in `exec_no_cache'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:664:in `block in exec_query'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activesupport-3.2.5/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:663:in `exec_query'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:1246:in `select'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/querying.rb:38:in `block in find_by_sql'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.2.5/lib/active_record/explain.rb:40:in `logging_query_plan'
... 12 levels...
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:273:in `signal_status'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:156:in `block in eval_input'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb/ruby-lex.rb:243:in `block (2 levels) in each_top_level_statement'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `loop'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `block in each_top_level_statement'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `catch'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `each_top_level_statement'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:155:in `eval_input'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:70:in `block in start'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:69:in `catch'
from /Users/johnmerlino/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/irb.rb:69:in `start'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.5/lib/rails/commands/console.rb:47:in `start'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.5/lib/rails/commands/console.rb:8:in `start'
from /Users/johnmerlino/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.5/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'Maybe IRB bug!
I think that scopes are usually meant to return a custom subset / join of the model, which may be causing the SELECT "reports".* FROM "reports" query after the others complete. Since it looks like you're on Rails 3 or higher, I'd replace the scope with a class method (the Rails Guide says "Using a class method is the preferred way to accept arguments for scopes.").