{"action":"created","issue":{"url":"https://api.github.com/repos/rails/rails/issues/26848","repository_url":"https://api.github.com/repos/rails/rails","labels_url":"https://api.github.com/repos/rails/rails/issues/26848/labels{/name}","comments_url":"https://api.github.com/repos/rails/rails/issues/26848/comments","events_url":"https://api.github.com/repos/rails/rails/issues/26848/events","html_url":"https://github.com/rails/rails/issues/26848","id":184326808,"number":26848,"title":"ActiveJob AsyncAdapter swallows exceptions, doesn't log by default","user":{"login":"sbull","id":1115369,"avatar_url":"https://avatars.githubusercontent.com/u/1115369?v=3","gravatar_id":"","url":"https://api.github.com/users/sbull","html_url":"https://github.com/sbull","followers_url":"https://api.github.com/users/sbull/followers","following_url":"https://api.github.com/users/sbull/following{/other_user}","gists_url":"https://api.github.com/users/sbull/gists{/gist_id}","starred_url":"https://api.github.com/users/sbull/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sbull/subscriptions","organizations_url":"https://api.github.com/users/sbull/orgs","repos_url":"https://api.github.com/users/sbull/repos","events_url":"https://api.github.com/users/sbull/events{/privacy}","received_events_url":"https://api.github.com/users/sbull/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rails/rails/labels/activejob","name":"activejob","color":"5319e7"},{"url":"https://api.github.com/repos/rails/rails/labels/needs%20feedback","name":"needs feedback","color":"ededed"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-10-20T20:03:49Z","updated_at":"2016-10-21T13:26:25Z","closed_at":null,"body":"(On Rails 5.0.0.1)\r\n\r\nUsing the default AsyncAdapter in development, I was disappointed that I didn't see errors from my jobs even though I knew they were throwing exceptions (undefined methods, etc.). I would see the following messages in my log:\r\n\r\n    INFO -- : [ActiveJob] Enqueued MyJob ... (Job ID: f071893e-be9a-44fd-810c-5b38b270c58c) to Async(mail)...\r\n    ... <snip> ...\r\n    INFO -- : [ActiveJob] [MyJob] [f071893e-be9a-44fd-810c-5b38b270c58c] Performing MyJob from Async(mail)...\r\n    INFO -- : [ActiveJob] [MyJob] [f071893e-be9a-44fd-810c-5b38b270c58c] Performed MyJob from Async(mail)\r\n\r\nIf I set the following in an initializer:\r\n\r\n    Concurrent.global_logger = Concurrent.create_stdlib_logger(Logger::DEBUG)\r\n\r\nI get the errors printed on my terminal (not in `log/development.log`). I believe this is due to the logic in `Concurrent::RubyThreadPoolExecutor::Worker#run_task`.\r\n\r\nIt seems like with AsyncAdapter being the new development default, there should be something that notifies developers of job errors in the default setup. At least, perhaps an initializer that sets the Concurrent logger according to other Rails logger settings? But it might also be ideal for ActiveJob not to record \"Performed MyJob\", and instead say something like \"Failed MyJob\""},"comment":{"url":"https://api.github.com/repos/rails/rails/issues/comments/255376100","html_url":"https://github.com/rails/rails/issues/26848#issuecomment-255376100","issue_url":"https://api.github.com/repos/rails/rails/issues/26848","id":255376100,"user":{"login":"jdantonio","id":173910,"avatar_url":"https://avatars.githubusercontent.com/u/173910?v=3","gravatar_id":"","url":"https://api.github.com/users/jdantonio","html_url":"https://github.com/jdantonio","followers_url":"https://api.github.com/users/jdantonio/followers","following_url":"https://api.github.com/users/jdantonio/following{/other_user}","gists_url":"https://api.github.com/users/jdantonio/gists{/gist_id}","starred_url":"https://api.github.com/users/jdantonio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jdantonio/subscriptions","organizations_url":"https://api.github.com/users/jdantonio/orgs","repos_url":"https://api.github.com/users/jdantonio/repos","events_url":"https://api.github.com/users/jdantonio/events{/privacy}","received_events_url":"https://api.github.com/users/jdantonio/received_events","type":"User","site_admin":false},"created_at":"2016-10-21T13:26:25Z","updated_at":"2016-10-21T13:26:25Z","body":"This is expected behavior, but the suggested change is fairly easy. Please see PR #26852.\r\n\r\nApplication level exception handling is not a responsibility of `Concurrent::ThreadPoolExecutor`. Thread pools are low level abstractions. With respect to exception handling, the thread pool's only responsibility is to protect the integrity of the pool. Since unhandled exceptions in Ruby crash threads, `Concurrent::ThreadPoolExecutor` catches all exceptions not caught by the job proc and suppresses them, ensuring the continued operation of the thread. This is basic thread pool behavior and will probably never change.\r\n\r\nHigh level abstractions in concurrent-ruby all provide robust error handling and reporting features by passing a job wrapper to the thread pool. `Concurrent.global_logger` is used by some of the high level abstractions (like `Actor`) but not by all. It is not used directly by the thread pool ever. Changing `Concurrent.global_logger` will have no effect on any thread pool.\r\n\r\nWith respect to `AsyncAdapter`, exception handling was never part of the initial implementation since it was intended to only be used [for testing](https://github.com/rails/rails/pull/21257#issuecomment-131632785) only. Adding the suggested behavior will require a small update to the `JobWrapper` in `AsyncAdapter`.\r\n"}}
{"actor":{"display_login":"jdantonio"}}