Rails 4 ActiveJobs using different enqueue adapter and having NoMethodError - ruby-on-rails-4

I am trying to run an ActiveJob job from a controller method, but it fails and I can't spot the right place of the issue:
#app/controllers/users_controller.rb
1 class UsersController < ApplicationController
2 def new
3 #user = User.new
4 end1
5
6 def create
7 #user = User.create(user_params)
8 PoliciesChecksJob.new(#user.id).enqueue
9 # redirect to somewhere
10 end1
11 end
#app/jobs/policies_checks_job.rb
class PoliciesChecksJob < ActiveJob::Base
queue_as :default
def perform(user_id)
SearchPoliciesCommands.new.execute(user_id)
end
end
Logs summary:
Started POST "/users" for ::1 at 2015-03-30 15:01:03 +0100
Processing by UsersController#create as HTML
...(params)
(0.1ms) BEGIN
... (inserts the user)
(0.3ms) COMMIT
[ActiveJob] Enqueued PoliciesChecksJob (Job ID: da...e2) to Sneakers(default) with arguments: 1
Completed 500 Internal Server Error in 76ms
NoMethodError (private method `warn' called for nil:NilClass):
app/controllers/users_controller.rb:8:in `create'
I'd appreciate any thought.

Basically there was a little problem with the enqueue adapter:
I prefer to use Sneakers due the fact that it does work fine with RabbitMQ.
So I had to specify that I want a different enqueue adapter than the default one:
#config/application.rb
config.active_job.queue_adapter = :sneakers
Install RabbitMQ, and start it:
(preferible in a different terminal tab)
$ rabbitmq-server
Install the gem sneakers and run its deamon in (preferible other terminal tab):
$ sneakers work ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper
--require app/jobs/policies_checks_job.rb

Related

Flask-sqlalchemy / uwsgi: DB connection problem when more than on process is used

I have a Flask app running on Heroku with uwsgi server in which each user connects to his own database. I have implemented the solution reported here for a very similar situation. In particular, I have implemented the connection registry as follows:
class DBSessionRegistry():
_registry = {}
def get(self, URI, **kwargs):
if URI not in self._registry:
current_app.logger.info(f'INFO - CREATING A NEW CONNECTION')
try:
engine = create_engine(URI,
echo=False,
pool_size=5,
max_overflow=5)
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
a_session = Session()
self._registry[URI] = a_session
except ArgumentError:
raise Exception('Error')
current_app.logger.info(f'SESSION ID: {id(self._registry[URI])}')
current_app.logger.info(f'REGISTRY ID: {id(self._registry)}')
current_app.logger.info(f'REGISTRY SIZE: {len(self._registry.keys())}')
current_app.logger.info(f'APP ID: {id(current_app)}')
return self._registry[URI]
In my create_app() I assign a registry to the app:
app.DBregistry = DBSessionRegistry()
and whenever I need to talk to the DB I call:
current_app.DBregistry.get(URI)
where the URI is dependent on the user. This works nicely if I use uwsgi with one single process. With more processes,
[uwsgi]
processes = 4
threads = 1
sometimes it gets stuck on some requests, returning a 503 error code. I have found that the problem appears when the requests are handled by different processes in uwsgi. This is an excerpt of the log, which I commented to illustrate the issue:
# ... EVERYTHING OK UP TO HERE.
# ALL PREVIOUS REQUESTS HANDLED BY PROCESS pid = 12
INFO in utils: SESSION ID: 139860361716304
INFO in utils: REGISTRY ID: 139860484608480
INFO in utils: REGISTRY SIZE: 1
INFO in utils: APP ID: 139860526857584
# NOTE THE pid IN THE NEXT LINE...
[pid: 12|app: 0|req: 1/1] POST /manager/_save_task =>
generated 154 bytes in 3457 msecs (HTTP/1.1 200) 4 headers in 601
bytes (1 switches on core 0)
# PREVIOUS REQUEST WAS MANAGED BY PROCESS pid = 12
# THE NEXT REQUEST IS FROM THE SAME USER AND TO THE SAME URL.
# SO THERE IS NO NEED FOR CREATING A NEW CONNECTION, BUT INSTEAD...
INFO - CREATING A NEW CONNECTION
# TO THIS POINT, I DON'T UNDERSTAND WHY IT CREATED A NEW CONNECTION.
# THE SESSION ID CHANGES, AS IT IS A NEW SESSION
INFO in utils: SESSION ID: 139860363793168 # <<--- CHANGED
INFO in utils: REGISTRY ID: 139860484608480
INFO in utils: REGISTRY SIZE: 1
# THE APP AND THE REGISTRY ARE UNIQUE
INFO in utils: APP ID: 139860526857584
# uwsgi GIVES UP...
*** HARAKIRI ON WORKER 4 (pid: 11, try: 1) ***
# THE FAILED REQUEST WAS MANAGED BY PROCESS pid = 11
# I ASSUME THIS IS WHY IT CREATED A NEW CONNECTION
HARAKIRI: -- syscall> 7 0x7fff4290c6d8 0x1 0xffffffff 0x4000 0x0 0x0
0x7fff4290c6b8 0x7f33d6e3cbc4
HARAKIRI: -- wchan> poll_schedule_timeout
HARAKIRI !!! worker 4 status !!!
HARAKIRI [core 0] - POST /manager/_save_task since 1587660997
HARAKIRI !!! end of worker 4 status !!!
heroku[router]: at=error code=H13 desc="Connection closed without
response" method=POST path="/manager/_save_task"
DAMN ! worker 4 (pid: 11) died, killed by signal 9 :( trying respawn ...
Respawned uWSGI worker 4 (new pid: 14)
# FROM HERE ON, NOTHINGS WORKS ANYMORE
This behavior is consistent over several attempts: when the pid changes, the request fails. Even with a pool_size = 1 in the create_engine function the issue persists. No issue instead is uwsgi is used with one process.
I am pretty sure it is my fault, there is something I don't know or I don't understand about how uwsgi and/or sqlalchemy work. Could you please help me?
Thanks
What is hapeening is that you are trying to share memory between processes.
There are some exaplanations in these posts.
(is it possible to share memory between uwsgi processes running flask app?).
(https://stackoverflow.com/a/45383617/11542053)
You can use an extra layer to store your sessions outsite of the app.
For that, you can use uWsgi's SharedArea(https://uwsgi-docs.readthedocs.io/en/latest/SharedArea.html) which is very low level or you can user other approaches like uWsgi's caching(https://uwsgi-docs.readthedocs.io/en/latest/Caching.html)
hope it helps.

Suddenly, every test in our Rails 4 app fails

My co-workers tell me these tests pass when they run them. But I just checked the code out from Bitbucket, and for me, the tests fail. I made sure that my machine has the same version as my co-workers:
Rails 4.2.4
Ruby 2.2.3
rake, version 10.4.2
After some pain with nokogiri, I was able to get "bundle install" to run.
But if I do this:
bin/rake test
Every test fails:
27 runs, 0 assertions, 0 failures, 27 errors, 0 skips
with an error that looks like this:
6) Error:
ProfilesControllerTest#test_#update:
NoMethodError: undefined method `type' for nil:NilClass
Error:
ProfilesControllerTest#test_#update:
NoMethodError: undefined method `each' for nil:NilClass
Here is an example of some failing code:
require 'test_helper'
class ProfilesControllerTest < ActionController::TestCase
test '#update' do
profile = profiles(:no_address_profile)
login(profile)
VCR.use_cassette('essex_street_ny') do
patch :update, profile: {address: '15 Essex street, New York, NY, USA', zipcode: '10002'}
end
updated_profile = Profile.find_by_user_id(profile.user_id)
assert_equal '15 Essex street, New York, NY, USA', updated_profile.address
assert_equal '10002', updated_profile.zipcode
assert_redirected_to root_path
end
test '#update with only zipcode' do
profile = profiles(:no_address_profile)
login(profile)
VCR.use_cassette('only_10002_zipcode') do
patch :update, profile: {zipcode: '10002'}
end
updated_profile = Profile.find_by_user_id(profile.user_id)
assert_equal '10002', updated_profile.zipcode
assert_redirected_to root_path
end
def login(profile)
session[:user_id] = profile.user_id
end
end
So what is really happening here?
UPDATE:
If I do :
rake db:fixtures:load
I get:
rake aborted!
NoMethodError: undefined method `type' for nil:NilClass
It sounds like you need to run migrations in your test environment. You can do that like so:
rake db:migrate RAILS_ENV=test

Ruby on Rails 4 Whenever cron job working but not sure about output

I am newbie on Ruby on rails.
I have to implement auto-generate mail functionality with cronjobs using whenever gem and I have followed this link http://www.sitepoint.com/schedule-cron-jobs-whenever-gem/
What I have done---
1. Added user_notifier.rb file and set all mail actions as
class UserNotifier < ActionMailer::Base
default from: "myusername#example.com"
def two_hour_reminder
mail( :to => 'username#example.com' ,:subject => 'Reminder')
end
def mail_notification
UserNotifier.two_hour_reminder.deliver
end
end
2. Added schedule.rb
every 3.minutes do
rake 'send_digest_email'
end
3. Added scheduler.rake
desc 'send digest email'
task send_digest_email: :environment do
UserNotifier.mail_notification.deliver!
end
4. Added deploy.rb
require 'whenever/capistrano'
set :whenever_environment, defer { stage }
set :whenever_command, 'bundle exec whenever'
After this I have executed command grep CRON /var/log/syslog where i got following log
CMD (/bin/bash -l -c 'cd /home/username/repository && RAILS_ENV=production
bundle exec rake send_digest_email --silent')
But still I'm not getting any mail in inbox.
What I´m missing?
In schedule.rb, replaced rake 'send_digest_email' with command 'cd /home/username/repository && RAILS_ENV=development
bundle exec rake send_digest_email --silent'
:)

rake db:migrate fails with globalize gem and rails 4.1.7

I'm trying to use the globalize gem with Rails 4.1.7.
Using latest RVM version, os is Ubuntu 12.04, db is postgresql 9.3.
Following the instructions found in readme.md on github i added the translates directive in my model and scaffolded a migration
class Ingredient < ActiveRecord::Base
translates :name, :description
end
class CreateIngredientTranslations < ActiveRecord::Migration
def up
Ingredient.create.translation_table!({
name: :string,
descripion: :text
}, {
migrate_data: true
})
end
def down
Ingredient.drop_translation_table! migrate_data: true
end
end
Then when i do rake db:migrate i get the following error
PG::UndefinedTable: ERROR: relation "ingredient_translations" does not exsist
LINE 5: WHERE a.attrelid = '"ingredient_translations"...
^
: SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = '"ingredient_translations"'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum
/home/kranz/.rvm/gems/ruby-2.1.4#recipes/gems/activerecord-4.1.7/lib/active_record/connection_adapters/postgresql_adapter.rb:822:in `async_exec'
This is really weird.
Googling around for this kind of error I found a ticket in github
https://github.com/globalize/globalize/issues/288
opened in Dec 2013 and still not closed which seems very similar; the only solution seems to be a hack in globalize code, but i'd prefer not to monkey patching code at that level.
Is it due to the combination of postgres and globalize or there is any other solution to this?

rails 4 flash not persisting across redirect "ActionDispatch::Request::Session -- not yet loaded"

I am having a weird issue where a flash message is not persisting across redirects in a Rails 4.0.2 application. I suspect that the problem has something to do with the session not yet being loaded when I try to access the flash hash as I am logging the session and getting the following output:
#<ActionDispatch::Request::Session:0x7ffda10835a8 not yet loaded>
I am trying to update an asset in the 'assets_controller' and then redirect to the 'home' action of the 'dashboard_controller' if the asset was successfully updated. My code is as follows:
AssetsController:
def update
#asset = Asset.update_asset(asset_parameters, params[:id])
if #asset.errors.any?
flash.now[:error] = "There were some errors"
render 'edit'
else
flash[:success] = "Asset updated!"
logger.debug("flash in assets: #{flash.inspect}")
redirect_to root_path()
end
end
DashboardController:
def home
logger.debug("session #{session.inspect}")
logger.debug("flash in home #{flash.inspect}")
res = Bid.bids_query({:generation => 'current'})
#bids = []
#staging_jobs = []
res.each do |bid|
bid.staging_job_id ? #staging_jobs << bid : #bids << bid
end
end
Log Output:
Started PATCH "/assets/19" for 127.0.0.1 at 2014-03-16 21:45:53 -0700
Processing by AssetsController#update as HTML
flash in assets: #<ActionDispatch::Flash::FlashHash:0x007ff7abdcfc30 #discard=#<Set:
{}>, #flashes={:success=>"Asset updated!"}, #now=nil>
Redirected by /Users/louism2/rails_projects/rosebank-
b/app/controllers/assets_controller.rb:31:in `update'
Redirected to http://localhost:3000/
Completed 302 Found in 14ms (ActiveRecord: 2.4ms)
Started GET "/" for 127.0.0.1 at 2014-03-16 21:45:53 -0700
Processing by DashboardController#home as HTML
session #<ActionDispatch::Request::Session:0x7ffda10835a8 not yet loaded>
flash in home #<ActionDispatch::Flash::FlashHash:0x007ff7abe743e8 #discard=#<Set: {}>,
#flashes={}, #now=nil>
Completed 200 OK in 81ms (Views: 53.7ms | ActiveRecord: 2.6ms)
The issue had to do with the fact that my model was named "assets" and that was somehow conflicting with the asset pipeline. The trick was to prefix the asset pipeline with an identifier other than assets which you can specify in your application.rb file with the following line:
config.assets.prefix = '/new_name_for_asset_pipeline'