Why won't my Twilio SMS send in Sidekiq background worker? - ruby-on-rails

I am having issues sending a text with Twilio through my SideKiq background worker. The worker is supposed to send a text and then send an email (with Mandrill).
The email works fine.
The text never happens.
I haven't had issues with other jobs (including ones that also involve use
of environment variables).
I haven't had issues sending Twilio texts outside of a background worker.
I'm using Foreman to start my application.
In console, running UserNotifier.new.perform(1) works fine - both the email and the text are sent.
Here is some of the code in question:
This is the class that I'm using to send my SMS:
(My Gemfile includes the twilio-ruby gem)
class SendSMS
def initialize
#twilio_client = Twilio::REST::Client.new "#{ENV['TWILIO_SID']}", "#{ENV['TWILIO_TOKEN']}"
end
def send(message, user)
#twilio_client.account.sms.messages.create(
:from => "+1#{ENV['TWILIO_PHONE_NUMBER']}",
:to => user.phone_number,
:body => message
)
end
end
My worker looks like this:
class UserNotifier
include Sidekiq::Worker
sidekiq_options queue: :immediate
def perform(user_id)
user = User.find(user_id)
message = "Hi #{user.name}!"
SendSMS.new.send(message, user)
UserMailer.send(message, user).deliver
end
end
Can anyone see an issue with my code? Please let me know if there is anything else I should post or if there is any clarification that I could make.
My server was displaying the worker logs and it didn't seem to be running into an error.
Any suggestions on how to debug background workers would be appreciated as well.

Try catching REST errors from Twilio and logging some debug info. You can discover errors that might prevent messages from sending, or investigate sent messages in your Twilio account logs via their sid (Twilio's internal id). Also updated your create call to use the messages resource instead of deprecated sms/messages.
begin
message = #twilio_client.account.messages.create(
:from => "+1#{ENV['TWILIO_PHONE_NUMBER']}",
:to => user.phone_number,
:body => message
)
logger.debug "sent #{message.sid}"
rescue Twilio::REST::RequestError => e
logger.debug "error: #{e.message}"
end

Related

Where can i put this rabbitmq consumer code?

I have this code of a rabbitmq consumer using bunny that should listen to messages published to a rabbitmq queue and display a flash notice on the view whenever a message is consumed. The consumer is running in a different session from the producer though they are in the same application. The application uses a direct exchange which uses the message receiver's email as the routing_key. I would like when a message with a routing_key similar to the current_user's email is published, a flash message is displayed for that user indicating that he has a new message without refreshing the page. I want behavior similar to Facebook notifications.
The producer code looks like this:
class MessagesController < ApplicationController
def create
#message = Message.new(message_params)
#message.creator_id = current_user.id
#message.receiver_id = params[:message][:receiver_id]
if #message.save
email = #message.receiver.email
$message_exchange.publish(#message.content, :routing_key => email)
redirect_to user_path(current_user)
end
end
The consumer code: looks like this:
email = current_user.email
$message_queue.bind($message_exchange, :routing_key => email)
logger.info " [*] Waiting for messages. To exit press CTRL+C"
$message_queue.subscribe(:manual_ack => true) do |delivery_info, properties, body|
logger.info " [x] #{delivery_info.routing_key}:#{body}"
if delivery_info.routing_key == current_user.email
flash[:notice] = "you have new message: #{body}"
end
end
The problem is that i don't know where to put the consumer code. I have tried putting the code as a method in the application controller but this does not seem to work. Any suggestion on how to do this better is highly appreciated.

Sending sms from twilio in rails

new to ruby/rails here so please forgive my ignorance. Working on adding SMS capabilities to an existing app and I’ve been successful while just setting up a ruby document and sending a sms message but when I go to incorporate it in my rails app, I’m getting a little lost.
I’ve followed this document (https://www.twilio.com/blog/2012/02/adding-twilio-sms-messaging-to-your-rails-app.html) and created a SendTextController with the following code but included the account_sid and account_token in my application.yml file using ENV and figaro. In my actual file, I have my twilio phone number and the number I'd like to send it to (just blocked it out here).
Once I set this up, I’m lost at how to call this method from a view in my app?
class TwilioController < ApplicationController
def index
end
def send_text_message
number_to_send_to = "+1XXXXXXXXXX"
twilio_sid = ENV["TWILIO_SID"]
twilio_token = ENV["TWILIO_TOKEN"]
twilio_phone_number = "+1XXXXXXXXXX"
#twilio_client = Twilio::REST::Client.new twilio_sid, twilio_token
#twilio_client.account.sms.messages.create(
:from => "+1#{twilio_phone_number}",
:to => number_to_send_to,
:body => "Test Message from testing"
)
end
end
Your code to send the text message looks pretty much solid - if you have that code defined in your controller, and you'd like to call it when rendering, say, the index view of your TwilioController, you should be able to call self.send_text_message().
But if you're just getting started (and presumably using Rails 4?) there's a more up-to-date tutorial that can take you through the entire integration process.

Testing ActiveSupport::Notifications with rspec

Does anybody know how you can spec an active support notification? The following doesn't seem to work. It detects the default rails framework notifications but not my custom one.
it 'sends a "product.search" notification to any subscribers listening'
ActiveSupport::Notifications.should_receive(:instrument).with("product.search", :search => search)
get :search, ...
end
If I change the spec to check the outcome of the subscriber's code (e.g. record count change when creating a DB record) it passes. That confirms that it is working ok. But, it seems wrong to spec what the subscriber does here, I just want to spec that the notification is being sent. Any thoughts would be appreciated.
EDIT:
Here is the controller code that I'm trying to spec:
ActiveSupport::Notifications.instrument("product.search", :search => 'test')
I had the same issue and wrote the following rspec helper method below:
def notification_payload_for(notification)
payload = nil
subscription = ActiveSupport::Notifications.subscribe notification do |name, start, finish, id, _payload|
payload = _payload
end
yield
ActiveSupport::Notifications.unsubscribe(subscription)
return payload
end
This way, I can use it as follows:
it "should raise the my_notification_name notification" do
payload = notification_payload_for('my_notification_name') do
# do stuff that should raise the proper notification
end
# test to see that the payload has the correct info
end
I was unable to achieve the test using a regular :get action, something should interfere somehow and only start_processing and process_action notifications are triggered. I guess it has been disabled for performance sake.
But this successfully works:
it 'sends a "product.search" notification to any subscribers listening'
ActiveSupport::Notifications.should_receive(:instrument).with("product.search", :search => "test")
controller.index
end

How does one use delayed_job to make an Rails 3.0 ActionMailer run asynchronously? Encountering ArgumentErrors

I'm trying to delay a notification email to be sent to users upon signing up to my app. The emails are sent using an ActionMailer which I call InitMailer. The way I am trying to delay the jobs is using collectiveidea's delayed_job https://github.com/collectiveidea/delayed_job. To do this you can see that i specify handle_asynchronously after defining the method initial_email:
class InitMailer < ActionMailer::Base
default :from => "info#blahblahblah.com"
def initial_email(user)
#user = user
#url = "http://www.blahblahblah.com"
mail(:to => user.email,
:subject => "Welcome to my website!"
)
end
handle_asynchronously :initial_email
end
However, I encounter an argument error in my log file "delayed_job.log":
Class#initial_email failed with ArgumentError: wrong number of arguments (1 for 0) - 5
failed attempts
For your information, the email is sent in a controller using the line:
#user = InitUser.new(params[:init_user])
InitMailer.delay.initial_email(#user)
Additionally, when I set up my code without the delay, the emails were sent out without problem (except for the fact that it slowed down my app waiting for gmail servers)
Where is causing the errors here? How can I get the delayed mail to send properly?
Due to the way that Rails3 implements mailers, there are some unusual workarounds for delayed_jobs. For instance, you have seen that to delay the mailing, you write
ExampleMailer.delay.example(user)
While typically you would have to write handle_asynchronously after the method definition, in the case of mailers this declaration (for some reason) prevents that delayed job from working.
So in this code, drop the declaration entirely:
class InitMailer < ActionMailer::Base
default :from => "info#blahblahblah.com"
def initial_email(user)
#user = user
#url = "http://www.blahblahblah.com"
mail(:to => user.email,
:subject => "Welcome to my website!"
)
end
#No handle_asynchronously needed here
end

Delayed_Jobs will not refresh

I had previously a mailer set up to send me emails to all user accounts. But now I'm trying to debug it. So I gutted it out completely and it still sends emails to me.
I have absolutely no reasoning or understanding as to why. Insanity! :D
controller
def org_blast_send
Delayed::Job.enqueue OrgBlast.new(params[:subject], params[:editor1])
redirect_to org_blast_admin_email_blast_path
end
org_blast.rb
class OrgBlast < Struct.new(:subject, :editor1)
def perform
# You see? There is absolute nothing here but it still sends an email.
# However, if I rename this file, the website fails looking for it.
end
end
notifier.rb
def org_blast(org, subject, message)
subject subject
from NOTIFIER_EMAIL
recipients org.users.first.email
sent_on Time.zone.now
body :user => org.users.first.first_name + ' ' + org.users.first.last_name, :message => message
content_type "text/html"
end
If you are running delayed_jobs on your local, it must be stopped and restarted or it will despite your code do whatever was in your code the last time it was started.
>> script/delayed_job stop
>> script/delayed_job start

Resources