I am trying to log the output of a rake task to a new logger. Ideally the solution would work in development and production.
Here is my task:
task :clients, [:field] => [:setup_logger] do |t, args|
clients = Client.all
problems = []
group = clients.group_by { |client| client[args[:field]] }
unique_ids = group.keys
unique_ids.each do |unique_id|
problems << [unique_id, group[unique_id].length] if group[unique_id].length != 1
end
if !problems.blank?
logger = Logger.new("db_issues.log")
logger.error "look at me"
logger.close
end
p problems
end
When I run this, even though problems is not blank, no new log file is created. How am I supposed to accomplish this?
The problem is the logger.close, look after boot you server for a message like this:
log writing failed. closed stream
try removing logger.close from your code and restarting your server.
Related
Hi I have a rake task which when executed via console work, but doesn't work when rake task is called. Actually it confirms that save occurred, while values aren't updated. Seems like some active record commit is missing, because the only difference in logs I see is begin commit dumps if run (via console), while there isn't such sections in Redmine's debug.log when run as rake task...
Here is it's content:
namespace :redmine do
namespace :myplugin do
desc 'Updates custom field for idle tickets.'
task :update_idle => :environment do
Issue.open.each do |issue|
begin
days = DateTime.now.to_time - DateTime.parse(issue.updated_on.to_s).to_time
days = days/86400
if days > 0
cfv = issue.custom_field_values.detect {|cfv| cfv.custom_field_id == 19 }
cfv.value = days.ceil
if issue.save
puts "#{issue.id} saved"
else
puts "#{issue.id} not saved"
end
end
end
end
end
end
end
The problem with above code is, that it works in Redmine 3.4 both in console, and as Rake task, but in Redmine 4, it only works in console.
Eventually I was able to perform change on issue's custom field on Redmine 4 via Rake task in the following way:
namespace :redmine do
namespace :myplugin do
desc 'Updates custom field for idle tickets.'
task :update_idle => :environment do
Issue.open.each do |issue|
begin
days = DateTime.now.to_time - DateTime.parse(issue.updated_on.to_s).to_time
days = days/86400
if days > 0
issue.custom_values.each do |x|
if x.custom_field_id == 19
x.value = days.ceil
x.save
end
end
issue.save
true
end
end
end
end
end
end
I have a rake file that is being called by a job scheduler. The file outputs the desc but I am not able to log anything else to the console. What am I missing?
inbox.rake
namespace :inbox do
desc 'Check inbox for new app builds'
task process_inbox: :environment do
puts "my task is working"
end
end
Similar to Heroku logs, you need STDOUT to see the outputs. Could be as simple as
my_logger = Logger.new(STDOUT)
my_logger.info "work or die"
puts sends the text to STDOUT, which is different when you run rake from the terminal versus invoking from another ruby process.
Where do you expect to see this text?
Try manually printing to console.
namespace :inbox do
desc 'Check inbox for new app builds'
task process_inbox: :environment do
Rails.logger.info "my task is working"
end
end
You're not using --quiet / --silent are you?
I am writing a Ruby on Rails application which has a Rake task that can parse a CSV file.
Here is the code:
desc "Import Channels into DB\n Usage: rake channel_import"
task :import_channels, :path_to_channel_list do |t, args|
require "#{Rails.root}/app/models/channel"
require "csv"
filePath = args.path_to_channel_list
puts "Filepath received = #{filePath}"
csv = CSV.read("#{filePath}", :encoding => 'windows-1251:utf-8')
csv.each_with_index do |row, i|
if [0].include?(i)
puts "Skipping over row #{i}"
next
end
if(row.nil?)
puts "row[#{i}] was nil"
else
channelName = nil
classif = nil
owner = nil
channelName = row[0].force_encoding('UTF-8')
classif = row[1].force_encoding('UTF-8')
owner = row[2].force_encoding('UTF-8')
if (channelName.nil?)
puts "Channel name for row #{i} was nil"
#add entry to Log file or errors database
next #skip this row of the csv file and go to next row
else
channel_hash = Hash.new("name" =>"#{channelName}", "classification" => "#{classif}", "owner" => "#{owner}" )
end
puts "\nChannel Name = #{channelName}\nClassification = #{classif}\n Ownership = #{owner}"
#If channel name exists in the Database, update it
xisting_channel = nil
xisting_channel = Channel.find_by channel_name: '#{channelName}'
if(xisting_channel.nil?)
#create a new channel
#new_channel = Channel.create(channel_hash)
puts "Inserted....#{#new_channel.inspect}"
else
#update existing channel
Channel.update(xisting_channel.id, :classification => "#{classif}", :ownership => "#{owner}" )
puts "Updated...."
puts "channel_hash = #{channel_hash.inspect} "
end#end if/else
end#end if/else
end #end CSV.each
end
When I run this code I get the following error message:
MRMIOMP0903:am AM$ rake import_channels[/XXXXXXXX/Channellist.csv]
Filepath received = /XXXXXXX/Channellist.csv
Skipping over row 0
Channel Name = APTN HD+
Classification = Specialty
Ownership = Aboriginal Peoples Television Network
rake aborted!
ActiveRecord::ConnectionNotEstablished
I tried to create a Channel object using IRB and it worked just fine. The DB is created and I'm seeing it using MySQL WorkBench. All tables are there, however, I am unable to create the Channel object from the Rake task.
My hypothesis is, perhaps outside of a certain folder/hierarchy the app cannot access the ActiveRecord::Base class or something like this.
Any suggestions on how to make this work?
UPDATE:
BAsed on the answer by Phillip Hallstrom
I changed the top line to load the environment
task :import_channels => :environment do|t, args|
Then tried rake import_channels and got this error:
rake aborted!
undefined method `safe_constantize' for #<Hash:0x007fbeacd89920>
You need to load the environment prior to running your Rake task. I'm not familiar with your multiple task name options there, but for a simple example, you'd want this:
task : import_channels => :environment do
I have two questions:
How can I add a heroku worker just before running a delayed job and remove it after it finishes?
Is my cron.rake ok?
cron.rake:
desc "This task is called by the Heroku cron add-on"
task :cron => :environment do
puts "requesting homepage to refresh cache"
uri = URI.parse('http://something.com')
Net::HTTP.get(uri)
puts "end requesting homepage"
puts "start sending daily mail"
User.notified_today.each do |user|
Delayed::Job.enqueue UserMailer.daily_mail(user).deliver
end
puts "end sending daily mail"
end
I use collectiveidea delayed_job.
I've had good success with HireFire.
Easy setup:
Add gem 'hirefire' to your Gemfile
Create Rails.root/config/initializers/hirefire.rb with the config information.
To add remove/remove workers, hook into your ORM's after :create / after :destroy
With DataMapper on Heroku, I did it like this (You must set the ENV vars yourself)
MAX_CONCURRENT_WORKERS = 5
if ENV["HEROKU_APP"]
Delayed::Job.after :create do
workers_needed = [Delayed::Job.count, MAX_CONCURRENT_WORKERS].min
client = Heroku::Client.new(ENV['HEROKU_USERNAME'], ENV['HEROKU_PASSWORD'])
client.set_workers(ENV['HEROKU_APP'], workers_needed)
puts "- Initialized Heroku workers for ZipDecoder"
end
Delayed::Job.after :destroy do
workers_needed = [Delayed::Job.count, MAX_CONCURRENT_WORKERS].min
client = Heroku::Client.new(ENV['HEROKU_USERNAME'], ENV['HEROKU_PASSWORD'])
client.set_workers(ENV['HEROKU_APP'], workers_needed)
puts "- Cleaned Up a Delayed Job for ZipDecoder ---------------------------------"
end
end
You maybe can use an "autoscale" plugin like workless or heroku-autoscale.
About the cron I don't see any problem on it...
I'd like to run a rake task (apn:notifications:deliver from the apn_on_rails gem) from a delayed_job. In other words, I'd like enqueue a delayed job which will call the apn:notifications:deliver rake task.
I found this code http://pastie.org/157390 from http://geminstallthat.wordpress.com/2008/02/25/run-rake-tasks-with-delayedjob-dj/.
I added this code as DelayedRake.rb to my lib directory:
require 'rake'
require 'fileutils'
class DelayedRake
def initialize(task, options = {})
#task = task
#options = options
end
##
# Called by Delayed::Job.
def perform
FileUtils.cd RAILS_ROOT
#rake = Rake::Application.new
Rake.application = #rake
### Load all the Rake Tasks.
Dir[ "./lib/tasks/**/*.rake" ].each { |ext| load ext }
#options.stringify_keys!.each do |key, value|
ENV[key] = value
end
begin
#rake[#task].invoke
rescue => e
RAILS_DEFAULT_LOGGER.error "[ERROR]: task \"#{#task}\" failed. #{e}"
end
end
end
Everything runs fine until the delayed_job runs and it complains:
[ERROR]: task "apn:notifications:deliver" failed. Don't know how to build task 'apn:notifications:deliver'
How do I let it know about apn_on_rails? I'd tried require 'apn_on_rails_tasks' at the top of DelayedRake which didn't do anything. I also tried changing the directory of rake tasks to ./lib/tasks/*.rake
I'm somewhat new to Ruby/Rails. This is running on 2.3.5 on heroku.
Why don't do just a system call ?
system "rake apn:notifications:deliver"
I believe it's easier if you call it as a separate process. See 5 ways to run commands from Ruby.
def perform
`rake -f #{Rails.root.join("Rakefile")} #{#task}`
end
If you want to capture any errors, you should capture STDERR as shown in the article.