Not able to hit mixpanel in delayed job? - ruby-on-rails

I am using delayed_job to do some background task. In between I want to track some events. I am using mixpanel gem to track the events. In controller its working perfectly fine. But not in Delayed Job.
Code I am using
#original_message = Message.find(message_id)
#mixpanel= Mixpanel::Tracker.new("43242637426346287482", message_id, true)
#mixpanel.track_event("blank_body", {:reset_result => "sucess" })
//message_id is a unique for every request.
I have specified
gem 'mixpanel' in gemfile
{undefined method `[]=' for 45:Fixnum
/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/mixpanel-0.9.0/lib/mixpanel/tracker.rb:38:in clear_queue'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/mixpanel-0.9.0/lib/mixpanel/tracker.rb:13:ininitialize'\n/Users/mohit/projects/textadda/lib/message_job.rb:109:in new'\n/Users/mohit/projects/textadda/lib/message_job.rb:109:inperform'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/backend/base.rb:87:in invoke_job'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:120:inrun'\n/Users/mohit/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/timeout.rb:67:in timeout'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:120:inrun'\n/Users/mohit/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:in realtime'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:119:inrun'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:177:in reserve_and_run_one_job'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:104:inwork_off'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:103:in times'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:103:inwork_off'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:78:in start'\n/Users/mohit/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:inrealtime'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:77:in start'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:74:inloop'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/worker.rb:74:in start'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/delayed_job-2.1.4/lib/delayed/tasks.rb:9\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/task.rb:205:incall'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/task.rb:205:in execute'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/task.rb:200:ineach'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/task.rb:200:in execute'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/task.rb:158:ininvoke_with_call_chain'\n/Users/mohit/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/monitor.rb:242:in synchronize'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/task.rb:151:ininvoke_with_call_chain'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/task.rb:144:in invoke'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:112:ininvoke_task'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:90:in top_level'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:90:ineach'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:90:in top_level'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:129:instandard_exception_handling'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:84:in top_level'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:62:inrun'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:129:in standard_exception_handling'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/lib/rake/application.rb:59:inrun'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/gems/rake-0.9.2/bin/rake:32\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/bin/rake:19:in `load'\n/Users/mohit/.rvm/gems/ruby-1.8.7-p334/bin/rake:19
EDIT
I have implemented mixpanel in background process using standard get request. But I am still looking for the solution how can I use Mixpanel gem in background process.

You should just be doing something like this:
#mixpanel= Mixpanel::Tracker.new("43242637426346287482", {:REMOTE_ADDR => message_id}, true)
#mixpanel.track_event("blank_body", {:reset_result => "sucess" })
The gem expects the second variable to be the request environment, so will get the ip address that way, and send that to mixpanel.com. But I am not even sure if that is really needed, so I think that even a simple
#mixpanel= Mixpanel::Tracker.new("43242637426346287482", {}, true)
#mixpanel.track_event("blank_body", {:reset_result => "sucess" })
should work.
Hope this helps.

NOTE: THIS ANSWER IS NOW OUT OF DATE AS OF OCT 15 2012 AS THE INITIALIZE METHOD NO LONGER TAKES A ENV PARAMETER
The example on https://github.com/zevarito/mixpanel Mixpanel::Tracker.new gets called like this:
Mixpanel::Tracker.new("YOUR_MIXPANEL_API_TOKEN", request.env, true)
In a controller context, request.env is a hash.
In your code above your passing in message_id as the second argument, which looks like an integer. Sorry, can't help anymore than that, don't know anything about the mixpanel gem, but that's the root of your problem.
If the mixpanel API documentation tells you you can pass an integer as the second parameter, it's incorrect. Here's the code relevant to your error from https://github.com/zevarito/mixpanel/blob/master/lib/mixpanel/tracker.rb
module Mixpanel
class Tracker
def initialize(token, env, async = false)
#token = token
#env = env
#async = async
clear_queue
end
# snip
def clear_queue
#env["mixpanel_events"] = []
end
# snip
end
end
Passing an integer as the second argument to the initializer will not work, because the Fixnum class doesn't have a hash assignment ([]=) method, which is exactly the error message you are getting.
If the documentation tells you this can be an integer, you should probably file an issue against mixpanel.

Related

Hash data being altered when sent to class

My endpoint sends params to a class/worker.
def end_point
SomeClass.new.perform(params)
end
SomeClass starts defining variables.
def perform(params)
#variable = params[:variable]
end
If I do #variable.count in a pry session, it will return 2. But if I do params[:variable].count, it returns 1(the correct value). The data is being altered from within the method.
I tried renaming the arguments from params, I tried setting the variable in pry manually (this will result in 1), but when it is defined inside the method, it still results in 2. I inspected to make sure nothing is being altered sending from the controller. Any help would be greatly appreciated.
params
{"variable"=>
[{"id"=>68,
"ed"=>5213,
"lo_id"=>2192,
"lo_name"=>"Arkan",
"state"=>"created",
"closed_at"=>nil,
"unstarted"=>false,
"crtal"=>0,
"cas_eived"=>0,
"or_payments"=>0,
"cips"=>0,
"g_sles"=>0,
"ters"=>0,
"itews"=>
[{"id"=>615,
"unit_re"=>{"id"=>708, "name"=>"each", "abbreviation"=>"ea", "quantity"=>"1.0", "stock_item_id"=>985, "default_for"=>["base"]},
"pce"=>0,
"nme"=>"1 Yer nant",
"sol]unt"=>0,
"cgory_id"=>nil,
"caty_name"=>"Uncategorized",
"sub_rows"=>nil,
"prev_count"=>0,
"preransfunt"=>0,
"pre_nt"=>0,
"staount"=>0,
"actrt_count"=>0,
"id_evecount"=>0,
"minsfers_out_ount"=>0,
"wasunt"=>0,
"grunt"=>0,
"ennt"=>0,
"ovunt"=>0,
"gont"=>0,
"quane"=>1,
"expunt"=>0,
"goes"=>0,
"staiance"=>0,
"vance"=>0,
"paramsToConvert"=>
["scount",
"pent_transfer_in_count",
"pent_transfer_out_count",
"s_end_count",
"o_count",
"e_count",
"g_count",
"a_start_count",
"m_transfers_in_count",
"m_transfers_out_count",
"g_count",
"w_count",
"s_count"]},
"action"=>"batch_print",
"controller"=>"s",
"event_id"=>"53",
"format"=>"pdf"
}

Nokogiri Timeout::Error when scraping own site

Nokogiri works fine for me in the console, but if I put it anywhere... Model, View, or Controller, it times out.
I'd like to use it 1 of 2 ways...
Controller
def show
#design = Design.find(params[:id])
doc = Nokogiri::HTML(open(design_url(#design)))
images = doc.css('.well img') ? doc.css('.well img').map{ |i| i['src'] } : []
end
or...
Model
def first_image
doc = Nokogiri::HTML(open("http://localhost:3000/blog/#{self.id}"))
image = doc.css('.well img')[0] ? doc.css('.well img')[0]['src'] : nil
self.update_attribute(:photo_url, image)
end
Both result in a timeout, though they work perfectly in the console.
When you run your Nokogiri code from the console, you're referencing your development server at localhost:3000. Thus, there are two instances running: one making the call (your console) and one answering the call (your server)
When you run it from within your app, you are referencing the app itself, which is causing an infinite loop since there is no available resource to respond to your call (that resource is the one making the call!). So you would need to be running multiple instances with something like Unicorn (or simply another localhost instance at a different port), and you would need at least one of those instances to be free to answer the Nokogiri request.
If you plan to run this in production, just know that this setup will require an available resource to answer the Nokogiri request, so you're essentially tying up 2 instances with each call. So if you have 4 instances and all 4 happen to make the call at the same time, your whole application is screwed. You'll probably experience pretty severe degradation with only 1 or 2 calls at a time as well...
Im not sure what default value of timeout.
But you can specify some timeout value like below.
require 'net/http'
http = Net::HTTP.new('localhost')
http.open_timeout = 100
http.read_timeout = 100
Nokogiri.parse(http.get("/blog/#{self.id}").body)
Finally you can find what is the problem as you can control timeout value.
So, with tyler's advice I dug into what I was doing a bit more. Because of the disconnect that ckeditor has with the images, due to carrierwave and S3, I can't get any info direct from the uploader (at least it seems that way to me).
Instead, I'm sticking with nokogiri, and it's working wonderfully. I realized what I was actually doing with the open() command, and it was completely unnecessary. Nokogiri parses HTML. I can give it HTML in for form of #design.content! Duh, on my part.
So, this is how I'm scraping my own site, to get the images associated with a blog entry:
designs_controller.rb
def create
params[:design][:photo_url] = Nokogiri::HTML(params[:design][:content]).css('img').map{ |i| i['src']}[0]
#design = Design.new(params[:design])
if #design.save
flash[:success] = "Design created"
redirect_to designs_url
else
render 'designs/new'
end
end
def show
#design = Design.find(params[:id])
#categories = #design.categories
#tags = #categories.map {|c| c.name}
#related = Design.joins(:categories).where('categories.name' => #tags).reject {|d| d.id == #design.id}.uniq
set_meta_tags og: {
title: #design.name,
type: 'article',
url: design_url(#design),
image: Nokogiri::HTML(#design.content).css('img').map{ |i| i['src']},
article: {
published_time: #design.published_at.to_datetime,
modified_time: #design.updated_at.to_datetime,
author: 'Alphabetic Design',
section: 'Designs',
tag: #tags
}
}
end
The Update action has the same code for Nokogiri as the Create action.
Seems kind of obvious now that I'm looking at it, lol. I dwelled on this for longer than I'd like to admit...

Rails code segment explained

I am working on an app which has the below code:
def app
#app ||= begin
if !::File.exist? options[:config]
abort "configuration #{options[:config]} not found"
end
app, myoptions = Rack::Builder.parse_file(self.options[:config], opt_parser)
self.myoptions.merge! myoptions
app
end
end
I am struggling to get my head around several parts of it..
#app||= begin...end
Does this mean that if #app does not exist the block is run?
app ,options = rack::builder
What does the comma do to it?
Please help
Your first assumptions was correct, it does say that if #app is nil, set it to whatever is returned in the block delimited with begin, end.
Regarding the comma, it works like this:
avar, bvar = "atest", "btest"
If you look at the source for Rack:Builder.parse_file then you will notice the last line
return app, options
So it is returning two values.
Hope that helps
#Craig-Taub ansewered the question,
I just want to add some notes:
Ruby commands are expressions which means they return value and you can assign them to variables.
You can read more about expressions and statements on Wikipedia and PragProg.
Second is that when you return more than one value in a code block, Ruby will wrap it into a simple array and return it to the caller.
That's why it works like that.

Delayed Job not saving new records

I have trying to save a new record with delayed job. The code in question is below:
#method being called:
ibo.add_to_database(params[:url])
#method definition
def add_to_database(url)
feed = Feeds.new do |f|
f.url = url
f.title = self.feed_title if self.feed_title
f.link = self.site_link if self.site_link
f.image = self.feed_image if self.feed_image
end
feed.save!
end
handle_asynchronously :add_to_database
I get absolutely no errors, and the job is removed from the database as it should be. Except there is no change to the Feeds model. Anyone have any ideas what gives?
delayed_job runs as a daemon thread, so the first thing to do would be to check whether that it is running:
ps ax | grep delayed_job
the next thing I would check the log of actual delayed job, it would probably have you error description:
less log/delayed_job.log
Other then that, your code sniplet looks fine.

Disable rails class_caching mechanism for Time.now?

I'm currently fighting with the rails class_caching mechanism as I need to return a file path that changes discrete over time. It is used to constantly change a log file path after the amount of GRAIN seconds and returns a fully working timestamp:
GRAIN = 30
def self.file_path
timestamp = (Time.now.to_i / GRAIN) * GRAIN
return FILE_DIR + "tracking_#{timestamp.call}.csv"
end
This works really great if the class_caching of rails is set to false. But of course the app is to run with enabled class caching. And as soon as I enable it, either the timestamp variable is cached or the Time.now expression.
I tried to solve this with a proc block, but no success:
def self.file_path
timestamp = Proc.new { (Time.now.to_i / GRAIN) * GRAIN }
return FILE_DIR + "tracking_#{timestamp.call}.csv"
end
Is there anything like a cache disabled scope I could use or something like skip_class_caching :file_path? Or any other solutions?
Thank you for your help!
It's not entirely clear where your code is located, but ActiveRecord has an uncached method that suspends the cache for whatever is inside its block.
I found the problem. Not the Time.now was beeing cached but a logger instance. It was assigned in another method calling the file_path.
As long as the class caching was disabled the environment forgot about the class variable between the requests. But as soon as it was enabled the class variable stayed the same - and desired value - but never changed.
So I had to add a simple condition that checks if the file_path changed since the last request. If so, the class variable is reassigned, otherwise it keeps the same desired value.
I changed from:
def self.tracker
file_path = Tracking.file_path
##my_tracker ||= Logger.new(file_path)
end
to:
def self.tracker
file_path = Tracking.file_path
##my_tracker = Logger.new(file_path) if ##my_tracker.nil? or Tracking.shift_log?(file_path)
##my_tracker
end
Thank you for your help anyways!

Resources