For some reason, my sidekiq worker can't read from my ActiveRecord models. Here is my worker class. It fails on line where its trying to read from my User object: name = User.find_by(id: user_id).first_name.
require 'gcm'
module Socio
class RequestNotificationWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(target_token, key)
begin
gcm = GCM.new(key)
registration_ids= [target_token]
options = {notification: {title: "Connection request!", body: "You have a new Socio request.",
sound: "default", badge: 1, type: "1"},
collapse_key: "New Connections", content_available: true, priority: "high"}
gcm.send(registration_ids, options)
{success: true}
rescue => e
{success: false, error: e.to_s}
end
end
end
class ConfirmNotificationWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(target_token, key)
begin
gcm = GCM.new(key)
name = User.find_by(id: #user_id).first_name
registration_ids= [target_token]
options = {notification: {title: "Connection Confirmed!", body: "#{name} has accepted your Socio request.",
sound: "default", badge: 1, type: "2"},
collapse_key: "New Connections", content_available: true, priority: "high"}
gcm.send(registration_ids, options)
{success: true}.to_json
rescue => e
{success: false, error: e.to_s}
end
end
end
end
Also here is my procfile:
web: bundle exec thin start -p $PORT
worker: bundle exec sidekiq -c 5 -v -r ./app/sidekiq.rb
And here is the error message:
Failed uninitialized constant Socio::ConfirmNotificationWorker::User
I tried different require and include commands, but couldn't get it to work.
Somewhere inside app/sidekiq.rb you need to require activerecord and user.rb. If you show us your sidekiq.rb it will help.
This is because app/sidekiq is not initializing your application - you have probably all relevant require statements in the main application file (app.rb). Compare app/sidekiq.rb with app.rb file (and possible other files in the tree) and add relevant require instructions in the first one.
You can also start the console session (for example using Pry: pry -r ./app/sidekiq.rb or built-in irb: irb -r ./app/sidekiq.rb) with app/sidekiq and check if all needed classes are there or even better: write specs to check if it works fine.
Related
I am following along with this stripe tutorial but the server.rb in the example from Stripe's Github is throwing an error when I run Ruby server.rb
I am very new to ruby so I could be doing things wrong.
What I did was:
Installed Ruby, Rails, Stripe CLI, Sinatra, and dotenv
Downloaded the example from the site by typing Stripe samples create
developer-office-hours
cd'd into the server directory and ran ruby
server.rb
this is the error
1: from server.rb:10:in '<main.'
server.rb:10:in 'join': no implicit conversation of nil into string (TypeError)
here is the server.rb file
require 'stripe'
require 'sinatra'
require 'dotenv'
# Replace if using a different env file or config
Dotenv.load
Stripe.api_key = ENV['STRIPE_SECRET_KEY']
set :static, true
set :public_folder, File.join(File.dirname(__FILE__), ENV['STATIC_DIR'])
set :views, File.join(File.dirname(__FILE__), ENV['STATIC_DIR'])
set :port, 4242
get '/' do
content_type 'text/html'
send_file File.join(settings.public_folder, 'index.html')
end
post '/webhook' do
# You can use webhooks to receive information about asynchronous payment events.
# For more about our webhook events check out https://stripe.com/docs/webhooks.
webhook_secret = ENV['STRIPE_WEBHOOK_SECRET']
payload = request.body.read
if !webhook_secret.empty?
# Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
sig_header = request.env['HTTP_STRIPE_SIGNATURE']
event = nil
begin
event = Stripe::Webhook.construct_event(
payload, sig_header, webhook_secret
)
rescue JSON::ParserError => e
# Invalid payload
status 400
return
rescue Stripe::SignatureVerificationError => e
# Invalid signature
puts "⚠️ Webhook signature verification failed."
status 400
return
end
else
data = JSON.parse(payload, symbolize_names: true)
event = Stripe::Event.construct_from(data)
end
# Get the type of webhook event sent - used to check the status of PaymentIntents.
event_type = event['type']
data = event['data']
data_object = data['object']
if event_type == 'some.event'
puts "🔔 Webhook received!"
end
content_type 'application/json'
{
status: 'success'
}.to_json
end
stripe login
This is a crucial step.
stripe samples create adding-sales-tax
cd adding-sales-tax/server
bundle install
If you don't have bundler, gem install bundler
bundle exec ruby server.rb
Open http://localhost:4242
unique_job_worker.rb
# -*- encoding : utf-8 -*-
require_relative 'logging_helper'
class UniqueJobWorker
include Sidekiq::Worker
include WorkerHelper
sidekiq_options retry: false,
backtrace: true,
queue: :sender,
failures: true
def perform(worker,campaign_guid, queue)
require'pry';binding.pry
end
end
unique_job_worker_test.rb
require 'test_helper'
require 'mocha/setup'
class UniqueJobWorkerTest < ActiveSupport::TestCase
def setup
require'pry';binding.pry
#worker = UniqueJobWorker.new
end
test "it exists" do
assert #worker
end
end
When enqueued through redis I get this response
INFO -- : Exception: uninitialized constant UniqueJobWorker
Any suggestions as to why my newly created worker, UniqueJobWorker, is not being found during runtime through redis or through a simple test?
Thanks ahead of time!
When you use sidekiq outside of Rails, you need to use the -r option to tell it how to load your workers. So (assuming that your worker is in a sub-directory called workers):
% sidekiq -r ./workers/unique_job_worker.rb
If you have multiple workers, an option is to create a loader file to ensure everything is loaded.
load_workers.rb
($LOAD_PATH << 'workers').uniq!
require 'unique_job_worker'
require 'other_worker'
...
Then require the loader file on the command line:
% sidekiq -r ./load_workers.rb
I had the same issue and ended up being a Redis namespace issue:
https://github.com/mperham/sidekiq/issues/2834#issuecomment-184800981
Adding that fixed it for me:
config.redis = {
url: ENV['REDIS_URL'],
namespace: "some_namespace_different_for_each_app"
}
You also need the redis-namespace gem BTW
In a Rails app, I have the following configuration to run System Rspec specs.
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :rack_test
end
config.before(:each, type: :system, js: true) do
driven_by :selenium, using: :headless_chrome, screen_size: [1300, 1240]
end
end
Now, I have added a middleware that depends upon env['REQUEST_PATH'] and, when I run the specs using rack_test I get
Failure/Error: _, id, request_path = env['REQUEST_PATH'].split('/', 3)
NoMethodError: undefined method `split' for nil:NilClass
However, if I always use selenium, all the specs pass like before.
Is there a way to use/set env['REQUEST_PATH'] with rack_test?
I'm working on a pure Ruby application where I'm trying to create a Rake task. I have a method in the file src/lambda_function.rb that is as follows:
def self.process(event:, context: nil, box_api: BoxApi.new, form: nil, sns: SNS.new, kms: KMS.new)
begin
# verify request came from fromstack from headers
verify_webhook_req(event)
# parse data
submission = JSON.parse(event["body"])
form_id = submission.fetch("FormID").strip()
submission_id = submission.fetch("UniqueID").strip()
As you can see from the above snippet the function takes in the following parameters:
event:, context:, box_api:, form:, sns:, kms: So in the rake task I pass the following:
require './src/lambda_function.rb'
require 'rake'
require 'pry'
include Rake::DSL
class KMS
def initialize
end
def decrypt(key)
return 'some password'
end
end
class SNS
def initialize
end
end
namespace :test do
namespace :lambda do
desc 'Run the Lambda process function'
task :process do
TEST_FORM_ID=3353951
LambdaFunctions::LambdaHandler.process(box_api: BoxApi.new,
form: TEST_FORM_ID,
sns: SNS.new,
kms: KMS.new)
end
end
end
But calling this rake task throws an error:
rake aborted!
ArgumentError: unknown keywords: box_api, form
How come it doesn't recognize form and box_api. At first, I thought that maybe I was missing a hash to pass in the arguments. {box_api: BoxApi.new, form: ....}` this didn't work either.
Why is throwing the error?
I was calling a method in a different class which had different parameters.
class WebhookHandler
def self.process(event:, context: nil, box_api: BoxApi.new, form: nil, sns: SNS.new, kms: KMS.new)
begin
# verify request came from fromstack from headers
verify_webhook_req(event)
Starting my mailman app by running rails runner lib/daemons/mailman_server.rb works fine.
When starting with my daemon script and command bundle exec rails runner script/daemon run mailman_server.rb, the script generates an error:
.rvm/gems/ruby-1.9.3-p194/gems/mailman-0.5.3/lib/mailman/route/conditions.rb:21:in `match': undefined method `each' for nil:NilClass (NoMethodError)
My code is as follows:
lib/daemons/mailman_server.rb
require 'mailman'
# Config Mailman
Mailman.config.ignore_stdin = false
Mailman.config.graceful_death = true
Mailman.config.poll_interval = 15
Mailman.config.logger = Logger.new File.expand_path("../../../log/mailman.log", __FILE__)
Mailman.config.pop3 = {
:username => 'alias#mygoogleapp.com',
:password => 'password',
:server => 'pop.gmail.com',
:port => 995,
:ssl => true
}
# Run the mailman
Mailman::Application.run do
from('%email%').to('alias+q%id%#mygoogleapp.com') do |email, id|
begin
# Get message without headers to pass to add_answer_from_email
if message.multipart?
reply = message.text_part.body.decoded
else
reply = message.body.decoded
end
# Call upon the question to add answer to his set
Question.find(id).add_answer_from_email(email, reply)
rescue Exception => e
Mailman.logger.error "Exception occured while receiving message:\n#{message}"
Mailman.logger.error [e, *e.backtrace].join("\n")
end
end
end
and my script/daemon file is:
#!/usr/bin/env ruby
require 'rubygems'
require "bundler/setup"
require 'daemons'
ENV["APP_ROOT"] ||= File.expand_path("#{File.dirname(__FILE__)}/..")
script = "#{ENV["APP_ROOT"]}/lib/daemons/#{ARGV[1]}"
Daemons.run(script, dir_mode: :normal, dir: "#{ENV["APP_ROOT"]}/tmp/pids")
Any insight as to why it fails as a daemon?