I'm running Rails 4.2 on Heroku (cedar), Ruby 2.1.6
I've got Sidekiq running locally on Redis with Foreman, and in my app I call Rails' new ActiveJob deliver_later methods like this, inside application_helper.rb
:
assigning_user = User.find(object.created_by)
completing_user = User.find(object.completed_by)
if NotificationMailer.assigned_user_completed_todo(object, completing_user, assigning_user).deliver_later
nn.email_status = "sent"
end
Locally, this works just as intended. Mails show up in the 'mailers' queue and then are processed and delivered using sendgrid.
On heroku run rails console
I can trigger it manually, and it works just fine:
Loading production environment (Rails 4.2.1)
irb(main):001:0> a = Account.first
Account Load (1.5ms) SELECT "accounts".* FROM "accounts" ORDER BY "accounts"."id" ASC LIMIT 1
=> #<Account id: 1, name: "The Prestons", stripe_customer_id: nil, active_until: "2015-06-27 14:50:43", plan: nil, created_at: "2015-04-27 14:50:43", updated_at: "2015-04-27 14:50:43">
irb(main):002:0> NotificationMailer.new_account_created(a).deliver_later
Enqueued ActionMailer::DeliveryJob (Job ID: 7c0ddf9c-6892-4aa9-823e-9954b2a4e642) to Sidekiq(mailers) with arguments: "NotificationMailer", "new_account_created", "deliver_now", gid://raisin/Account/1
=> #<ActionMailer::DeliveryJob:0x007f4d9ed9da58 @arguments=["NotificationMailer", "new_account_created", "deliver_now", #<Account id: 1, name: "The Prestons", stripe_customer_id: nil, active_until: "2015-06-27 14:50:43", plan: nil, created_at: "2015-04-27 14:50:43", updated_at: "2015-04-27 14:50:43">], @job_id="7c0ddf9c-6892-4aa9-823e-9954b2a4e642", @queue_name="mailers">
but if I simply complete actions in my app, the way I would as a user, nothing is ever delivered to the queue... I am totally out of ideas. I am running a worker process. I am connected to the redis cloud server. I can see the sidekiq web dashboard.
What am I not setting? Happy to provide other logs/info, but not sure what else to provide.
My console simply reports the action:
2015-05-14T09:14:37.674095+00:00 heroku[router]: at=info method=POST path="/accounts/1/projects/15/lists/33/items/112" host=www.myapp.com request_id=516db810-8a2c-4fd0-af89-29a59783b0a8 fwd="76.104.193.78" dyno=web.1 connect=1ms service=111ms status=200 bytes=2039
Embarrassingly, it turns out everything's working correctly, and the action I was doing to test email delivery via code would never have sent an email, because the user I was testing it with has email notifications turned off in settings.
Sigh.
But for posterity and for those who are trying to get Sidekiq to work on Heroku with Rails 4.2 and Redis Cloud, here are some pitfalls I encountered: The part that took me the most time to figure out was that in order to get Sidekiq to find your Redis server, you'll need to set the ENV variable IN Heroku (not in your code). So, at the console, first add e.g. rediscloud:
heroku addons:create rediscloud
And then you need to add the URL as an environment variable:
heroku config:set REDIS_PROVIDER=REDISCLOUD_URL
The Sidekiq documentation is super helpful. I used brew install redis
to install Redis locally, then redis-server
to run the server in a terminal window locally. Added gem 'sidekiq'
to the Gemfile and everything worked great in development.
If you add routes as shown here, you'll be able to monitor the queue in your web browser.
Lastly, don't forget that you need to add a worker in your Procfile
AND scale up to one worker in Heroku using heroku ps:scale worker=1
-- it won't start just because it's in your Procfile.
Also: when you put Sidekiq in your Procfile, be sure to tell it to process the mailers queue, e.g.
worker: bundle exec sidekiq -q default -q mailers