Sidekiq Twilio Redis 'undefined method `strip' for nil:NilClass' - ruby-on-rails

I'm using sidekiq and twilio to send a text at a specified time.
My message_worker.rb contains the following:
class MessageWorker
include Sidekiq::Worker
sidekiq_options retry: false
sidekiq_retries_exhausted do |msg|
Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}."
end
def perform(id)
record = Textmessage.find id
#twilio = Twilio::REST::Client.new ENV['ACCOUNT_SID'], ENV['AUTH_TOKEN']
#twilio.account.messages.create(
from: ENV['ACCOUNT_PHONE_NUMBER'],
to: record.phone_number,
body: 'This is your scheduled reminder to view a house.'
)
end
end
My redis.rb contains the following:
uri = URI.parse(ENV["REDISTOGO_URL"])
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
I am getting the following error message (I've spaced it for ease of reading):
Completed 200 OK in 245ms (Views: 180.7ms | ActiveRecord: 46.6ms)
2014-04-21T17:...
MessageWorker JID-... INFO: fail: 0.497 sec
2014-04-21T17:04:57.636194+00:00 app[web.1]:...
WARN: {"retry"=>false, "queue"=>"default", "class"=>"MessageWorker", "args"=>[5],
"jid"=>"...", "enqueued_at"=>...}
2014-04-21T17:04:57.636194+00:00 app[web.1]: 2014-04-21T17:04:57Z 5 TID-...
**WARN: undefined method `strip' for nil:NilClass**
2014-04-21T17:04:57.637073+00:00 app[web.1]: 2014-04-21T17:04:57Z 5 TID-...
WARN: /app/vendor/bundle/ruby/2.0.0/gems/twilio-ruby-3.11.5/lib/twilio-
ruby/rest/client.rb:142: in `initialize'

I needed to set my credentials that are inside of the ENV file. The format is as follows:
heroku config:set GITHUB_USERNAME=joesmith
You can also check out heroku's information on configuration variables (config vars): config vars on heroku

Related

NoMethodError - undefined method `get' for nil:NilClass

Here is the tutorial which I follow for implement: Finally Trying ActionCable
This code is too long, so I don't put this code into this question I just put some of the codes as like into the user model
def online_now?
$redis.get("users:online:#{id}").present?
end
and the view is:
<% User.all.each do |user| %>
<%= user.name %>
<div class="online-indicator">
<% if !user.online_now? && 'xs-none' %>
Online
<% else %>
Offline
<% end %>
</div>
<% end %>
but always throwing an error as like
NoMethodError - undefined method get' for nil:NilClass
Did you mean? gem:
app/models/user.rb:34:inonline_now?'
which indicating this line
$redis.get("users:online:#{id}").present?
I don't why throwing this error.
But it's working on rails console as like
irb(main):005:0> redis.set("mykey", "hello world")
=> "OK"
irb(main):006:0> redis.get("mykey")
=> "hello world"
Thanks
From comment #Ilya Konyukhov how do you define $redis variable in your model method. It's clear it should be a Redis API, but where do you connect to the Redis and store its connection?
Yes, that is a very nice comment & helpful for clearing the concept from a commentator.
If your Redis server is running in the system then need to configure this in Rails own way, I would writing some configuration files & if you already created that you can compare these & if you not created till now I think that is the issue & need to create ASAP if you need this feature.
First, install the gem redis-rails
gem 'redis-rails'
after that add this into environment file
config.cache_store = :redis_store, {
host: "localhost",
port: 6379,
db: 0,
password: "mysecret",
namespace: "cache"
}, {
expires_in: 90.minutes
}
create a file into app/config/initializer/ which redis.rb then put into this
$redis = Redis.new(:host => 'localhost', :port => 6379)
after all restart the server and check it out.
make sure redis-server is running.
Hope it will work.

NoMethodError (undefined method `fetch' for nil:NilClass)

Issue is with broadcasting data through a web socket using ActionCable. The error seems to suggest its coming from the create method.
Error Message
Rendered weight/_weight.html.erb (1.1ms)
[ActionCable] Broadcasting to weight: "<div class=\"row\">\n <div class=\"col-md-8 well\">\n <p>12.0 kg</p>\n <small>less than a minute</small>\n </div>\n</div>"
Completed 500 Internal Server Error in 25ms (Views: 7.4ms | ActiveRecord: 10.6ms)
NoMethodError (undefined method `fetch' for nil:NilClass):
app/controllers/weight_controller.rb:7:in `create'
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/_source.text.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/_source.text.erb (0.8ms)
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb (0.9ms)
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb (1.1ms)
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb (25.0ms)
Create method from controller.rb
def create
#weight = Weight.new(weight_params)
#weight.user_id = current_user.id
if #weight.save
ActionCable.server.broadcast "weight", render(partial: 'weight/weight', object: #weight)
else
flash[:danger] = "New Weight was not added!"
redirect_to current_user
end
end
private
def weight_params
params.require(:weights).permit(:weight)
end
I just cant work out what is returned as nil. The fact that the info is correct in what it is broadcasting to weight is correct suggests it has saves it correctly to the database. Can't think what else it is performing the 'fetch' method on.
Pretty sure the web socket is set up correctly. See below.
config/application.rb :
config.action_cable.mount_path = '/cable'
config/routes.rb :
mount ActionCable.server => '/cable'
weight_channel.rb :
def subscribed
stream_from "weight"
end
weight.coffee :
received: (data) ->
$("#messages").prepend(data)
The error was raised due to a missing config/cable.yml file.
The solution was to use a config/cable.yml with the required setting for the application. i.e.:
# Action Cable uses Redis by default to administer connections, channels, and sending/receiving messages over the WebSocket.
production:
adapter: redis
url: redis://localhost:6379/1
development:
adapter: redis
url: redis://localhost:6379/1
staging:
adapter: redis
url: redis://localhost:6379/1
test:
adapter: async
The resolution appears in the question's comments.

sneaker is not receiving messages on heroku - RabbitMQ Bigwig

I am trying to run message queues on heroku. For this I am using RabbitMQ Bigwig plugin.
I am publishing messages using bunny gem and trying to receive messages with sneakers gem. This whole setup works smoothly on local machine.
I take following steps to setup queue
I run this rake on server to setup queue:
namespace :rabbitmq do
desc 'Setup routing'
task :setup_test_commands_queue do
require 'bunny'
conn = Bunny.new(ENV['SYNC_AMQP'], read_timeout: 10, heartbeat: 10)
conn.start
ch = conn.create_channel
# get or create exchange
x = ch.direct('testsync.pcc', :durable => true)
# get or create queue (note the durable setting)
queue = ch.queue('test.commands', :durable => true, :ack => true, :routing_key => 'test_cmd')
# bind queue to exchange
queue.bind(x, :routing_key => 'test_cmd')
conn.close
end
end
I am able to see this queue in rabbitmq management plugin with mentioned binding.
class TestPublisher
def self.publish(test)
x = channel.direct("testsync.pcc", :durable => true)
puts "publishing this = #{Test}"
x.publish(Test, :persistent => true, :routing_key => 'pcc_cmd')
end
def self.channel
#channel ||= connection.create_channel
end
def self.connection
#conn = Bunny.new(ENV['RABBITMQ_BIGWIG_TX_URL'], read_timeout: 10, heartbeat: 10) # getting configuration from rabbitmq.yml
#conn.start
end
end
I am calling TestPublisher.publish() to publish message.
I have sneaker worker like this:
require 'test_sync'
class TestsWorker
include Sneakers::Worker
from_queue "test.commands", env: nil
def work(raw_event)
puts "^"*100
puts raw_event
# o = CaseNote.create!(content: raw_event, creator_id: 1)
# puts "#########{o}"
test = Oj.load raw_event
test.execute
# event_params = JSON.parse(raw_event)
# SomeWiseService.build.call(event_params)
ack!
end
end
My Procfile
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
worker: bundle exec rake jobs:work
sneaker: WORKERS=TestsWorker bundle exec rake sneakers:run
My Rakefile
require File.expand_path('../config/application', __FILE__)
require 'rake/dsl_definition'
require 'rake'
require 'sneakers/tasks'
Test::Application.load_tasks
My sneaker configuration
require 'sneakers'
Sneakers.configure amqp: ENV['RABBITMQ_BIGWIG_RX_URL'],
log: "log/sneakers.log",
threads: 1,
workers: 1
puts "configuring sneaker"
I am sure that message gets published. I am able to get message on rabbitmq management plugin. But sneaker does not work. There is nothing in sneakers.log that can help.
sneakers.log on heroku :
# Logfile created on 2016-04-05 14:40:59 +0530 by logger.rb/41212
Sorry for this late response. I was able to get this working on heroku. When I faced this error after hours of debugging I was not able to fix it. So I rewrote all above code and I did not check what was wrong with my previous code.
The only problem with this code and correct code is queue binding.
I had two queues on same exchange. pcc.commands with routing key pcc_cmd and test.commands with routing key test_cmd.
I was working with test_cmd but as per following line in TestPublisher
x.publish(Test, :persistent => true, :routing_key => 'pcc_cmd')
I was publishing to different queue(pcc.commands). Hence I was not able to recieve the message on test.commands queue.
In TestWorker
from_queue "test.commands", env: nil
This states that fetch messages only from test.commands queue.
Regarding sneakers.log file:
Above setup was not able to give me logs in sneakers.log file. Yes this setup works on your local development machine, but it was not working on heroku. Now days to debug such issue I ommit log attribute from configuration. like this:
require 'sneakers'
Sneakers.configure amqp: ENV['RABBITMQ_BIGWIG_RX_URL'],
# log: "log/sneakers.log",
threads: 1,
workers: 1
This way you will get sneaker logs (even heartbeat logs) in heroku logs which can be seen by running command heroku logs -a app_name --tail.

Faye Messaging on Heroku

I keep getting a 503 error 30 seconds after a client sends a message through faye. After the 30 seconds the client then receives the message and it is appended to the chat but the error still occurs and the socket will eventually close. How can i modify my existing code to keep the websocket alive? And how can I get rid of the 30 second delay that heroku throws when a message is sent?
messages/add.js.erb
<% broadcast #path do %>
var $chat = $("#chat<%= #conversation.id %>");
$chat.append("<%= j render(#message) %>");
//Set the scroll bar to the bottom of the chat box
var messageBox = document.getElementById('chat<%= #conversation.id %>');
messageBox.scrollTop = messageBox.scrollHeight;
<% end %>
$("#convoId<%=#conversation.id%>")[0].reset();
application_helper.rb
def broadcast(channel, &block)
message = {:channel => channel, :data => capture(&block), :ext => {:auth_token => FAYE_TOKEN}}
uri = URI.parse(FAYE_END_PT)
Net::HTTP.post_form(uri, :message => message.to_json)
end
application.rb
config.middleware.delete Rack::Lock
config.middleware.use FayeRails::Middleware, mount: '/faye', :timeout => 25
faye.ru
require 'faye'
require File.expand_path('../faye_token.rb', __FILE__)
class ServerAuth
def incoming(message, callback)
if message['channel'] !~ %r{^/meta/}
if message['ext']['auth_token'] != FAYE_TOKEN
message['error'] = 'Invalid authentication token'
end
end
callback.call(message)
end
end
Faye::WebSocket.load_adapter('thin')
faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 45)
faye_server.add_extension(ServerAuth.new)
run faye_server
Procfile
web: bundle exec rails server -p $PORT
worker: bundle exec foreman start -f Procfile.workers
Procile.workers
faye_worker: rackup middlewares/faye.ru -s thin -E production
503 Error
/messages/add Failed to load resource: the server responded with a status of 503 (Service Unavailable)
I tried adding a worker to heroku along with a web dyno with no luck. Everything works fine on my local host when running heroku local. The process on the local host look like
forego | starting web.1 on port 5000
forego | starting worker.1 on port 5100
worker.1 | 20:33:18 faye_worker.1 | started with pid 16534
where as even with the web dyno and worker on heroku
=== web (1X): bundle exec rails server -p $PORT
web.1: up 2015/12/28 20:08:02 (~ 1h ago)
=== worker (1X): bundle exec foreman start -f Procfile.workers
worker.1: up 2015/12/28 21:18:39 (~ 40s ago)
A lot of this code was taken from various tutorials so hopefully if we can solve this issue it will make using Faye with Heroku easier to someone else as well. Thanks!
Heroku has a 30 seconds timeout for all the requests, after that raise an H12 error. https://devcenter.heroku.com/articles/limits#http-timeouts
If your request takes more that 30 seconds you should consider put it into a background job using Delayed_Job or Sidekiq for example.

Getting 'Use MyMailer.delay.mailer_action(args) to delay sending of emails.' error

I am getting an odd error: 'Use MyMailer.delay.mailer_action(args) to delay sending of emails.' but I can seem to find out where does it come from:
app/mailers/user_notifier.rb
class UserNotifier < ActionMailer::Base
default from: "test#testing.com"
def signup_email(user)
#user = user
mail(to: #user.email, subject: t("mailer.signup.subject"))
end
...
end
In Console, the non-delayed one works:
UserNotifier.signup_email(user).deliver
but when adding delay, error occurs:
UserNotifier.signup_email(user).delay.deliver
Rendered user_notifier/signup_email.html.erb (0.7ms)
RuntimeError: Use MyMailer.delay.mailer_action(args) to delay sending of emails.
from /Users/quindici/.rvm/gems/ruby-2.1.2/gems/delayed_job-4.0.6/lib/delayed/performable_mailer.rb:20:in `delay'
from (irb):6
from /Users/quindici/.rvm/gems/ruby-2.1.2/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in `start'
from /Users/quindici/.rvm/gems/ruby-2.1.2/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in `start'
from /Users/quindici/.rvm/gems/ruby-2.1.2/gems/railties-4.0.0/lib/rails/commands.rb:64:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
It used to work but was broken sometimes ago. Still didn't get my head around it. Any idea would be much appreciated! Thank you.
When you use Delayed_job you'll can access .dealy method and then you can put the action mailer method like .deliver_later to delay sending of emails.
Simply way to add delayed_job in your project:
Add in your Gemfile:
gem "delayed_job_active_record"
gem "daemons"
Create the file "config/initializers/delayed_job_config.rb" with:
Delayed::Worker.destroy_failed_jobs = false
Delayed::Worker.sleep_delay = 60
Delayed::Worker.max_attempts = 3
Delayed::Worker.max_run_time = 5.minutes
Delayed::Worker.read_ahead = 10
Delayed::Worker.default_queue_name = 'default'
Delayed::Worker.delay_jobs = !Rails.env.test?
Delayed::Worker.raise_signal_exceptions = :term
Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))
In terminal:
$ bin/rails generate delayed_job:active_record
$ bin/rake db:migrate
$ bundle
$ bin/delayed_job start
Optional to view log: tail -f log/delayed_job.log
In some Mailer in your project (You can execute this in rails console):
SomeMailer.delay.some_method
Your queue will be processed in 60 seconds. You can remove the property Delayed::Worker.sleep_delay = 60 to process immediately.
Otherwise, you can configure your application to use delayed_job like your adapter for the active jobs and process works in background. Then you need to put config.active_job.queue_adapter = :delayed_job. This mode always you send an email you don't need to use .delay, instead, you call the mailer action and .deliver_later, for example: MyMailer.your_method.deliver_later. In this mode, the active job will enqueue the email in the delayed_job.
Questions and suggestions are welcome.
Reference: https://github.com/collectiveidea/delayed_job
I think you have it backwards:
UserNotifier.signup_email(user).delay.deliver
should be
UserNotifier.delay.signup_email(user)

Resources