4

In ./config/initializers I've created a file called task_scheduler.rb and it contains the following code:

require 'rufus-scheduler'
require 'mechanize'

scheduler = Rufus::Scheduler.new

scheduler.every("1h") do
    puts "Starting Rufus Scheduler - Task 1 - Checking exampleShop for new orders"

    a = Mechanize.new

    a.get('http://exampleshop.nl/admin/') do |page|

        # Select the login form
        login_form = page.forms.first

        # Insert the username and password
        login_form.username = 'username'
        login_form.password = 'password'

        # Submit the login information
        dashboard_page = a.submit(login_form, login_form.buttons.first)

        # Check if the login was successfull
        puts check_1 = dashboard_page.title == 'Dashboard' ?  "CHECK 1 DASHBOARD SUCCESS" : "CHECK 1 DASHBOARD FAIL"

        # Visit the orders index page to scrape some standard information
        orders_page = a.click(dashboard_page.link_with(:text => /Bestellingen/))

        # pp orders_page # => http://pastebin.com/L3zASer6

        # Check if the visit is successful
        puts check_2 = orders_page.title == 'Bestellingen' ?  "CHECK 2 ORDERS SUCCESS" : "CHECK 2 ORDERS FAIL"

        # Search for all #singleOrder table row's and put them in variable all_single_orders
        all_single_orders = orders_page.search("#singleOrder") 

        # Scrape the needed information (the actual save to database is omitted)
        all_single_orders.each do |order|
            # Set links for each order
            order_link = order.at_css("a")['href']  #Assuming first link in row

            @order_id = order.search("#orderId").text                   
            @order_status = order.search("#orderStatus").text       
            @order_revenue = order.search("#orderAmount").text      

            # Visit a single order page to fetch more detailed information
            single_order_page = orders_page.link_with(:href => order_link).click

            @first_name = single_order_page.search(".firstName").text
            @last_name = single_order_page.search(".lastName").text
            @city = single_order_page.search(".city").text
            @postal_code = single_order_page.search(".postalCode").text
            @address = single_order_page.search(".address").text
            @email = single_order_page.search(".email").text
            @order_quantity = single_order_page.search(".orderQuantity").text

            order = Order.create(   order_id: @order_id, first_name: @first_name, last_name: @last_name, city: @city,
                                                        email: @email, postal_code: @postal_code, address: @address, order_quantity: @order_quantity,
                                                        order_revenue: @order_revenue, order_status: @order_status)
        end
    end

    puts "Ending Rufus Scheduler - Task 1 - Checking exampleShop for new orders"
end

The rufus-scheduler works when testing in an development environment. But it stops working when I deploy the app to Heroku (free).

I'm using Phusion Passenger 4.0.27 as the application server.

My Gemfile looks like this:

source 'https://rubygems.org'
ruby '2.0.0'
gem 'rails', '4.0.1'
gem 'rufus-scheduler', '3.0.2'
gem 'pg'
gem 'mechanize'
gem 'bcrypt-ruby', '3.1.2'
gem 'sass-rails', '~> 4.0.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 1.2'
gem 'newrelic_rpm'

group :doc do
  gem 'sdoc', require: false
end

group :development do
    gem 'sqlite3'
end

group :production do
    gem 'rails_12factor'
    gem 'passenger'
    gem 'pg'
end

The Procfile required by Phusion Passenger contains the following:

web: bundle exec passenger start -p $PORT --max-pool-size 3

I have no workers running. I'm using one free standard web Dyno.

Any idea why rufus-scheduler is not working while deployed to Heroku?

UPDATE

I know I could create a customer .rake file and use the free Heroku Scheduler add-on to execute the task. But I'm wondering if there's a way to get the rufus-scheduler and free heroku dyno combination to work.

Community
  • 1
  • 1
narzero
  • 2,199
  • 5
  • 40
  • 73
  • Do you have any workers running? – Richard Peck Dec 10 '13 at 09:26
  • @RichPeck no, I'm using a single free standard Dyno. – narzero Dec 10 '13 at 09:28
  • 1
    Okay, the immediate issue you're going to have is that in order to run most types of scheduler, you'll need some sort of persistent worker running (to perform the jobs at the required time). You can use the standard `heroku scheduler add-on` but this only runs every 10 minutes. Running a worker won't fix your issue directly, but may be a contributing factor :) – Richard Peck Dec 10 '13 at 09:35
  • @narzero, did you resolve this? I'm running Rails 3.2.16 with Webrick, and rufus-scheduler *is* running, so I'm concerned to hear that sometimes it doesn't work. I wonder if it has to do with the amount of work your task does, or with the task needing access to the web. Have you tried it with a tiny test task, e.g. writing to a log? I don't quite understand how rufus-scheduler daemonizes its tasks within the web dyno. I've posted a related question here: http://stackoverflow.com/questions/22997650/rufus-scheduler-and-delayed-job-on-heroku-why-use-a-worker-dyno – Mark Berry Apr 10 '14 at 21:02
  • @MarkBerry I simply created a `.rake` task and used the `Heroku Scheduler` to execute it every 30 minutes. – narzero Apr 11 '14 at 06:58

3 Answers3

8

Here's an example of how to get it to work on Rails:

#
# config/initializers/scheduler.rb
require 'rufus-scheduler'

# Let's use the rufus-scheduler singleton
#
s = Rufus::Scheduler.singleton

# Awesome recurrent task...
#
s.every '1m' do
  Rails.logger.info "hello, it's #{Time.now}"
end

Take a look at the documentation.

narzero
  • 2,199
  • 5
  • 40
  • 73
1

You could instead use Heroku's Scheduler and move this task to work with Heroku's native tools : https://devcenter.heroku.com/articles/scheduler

benjaminjosephw
  • 4,369
  • 3
  • 21
  • 40
  • I know. But I'm wondering if there's a way to get the rufus-scheduler and free heroku dyno combination to work. – narzero Dec 10 '13 at 09:53
  • 1
    Looks like you'd need to set this up as a separate process in your procfile and scale up the that process - these docs are for clockwork but should mostly apply to rufus too: https://devcenter.heroku.com/articles/clock-processes-ruby – benjaminjosephw Dec 10 '13 at 10:07
  • Thanks, I'll play with that a little bit to see if it works for rufus-scheduler. – narzero Dec 10 '13 at 10:19
0

I solved this problem just adding to my Procfile:

web: bundle exec passenger start -p $PORT --max-pool-size 3 --min-instances 2

Bruno Casali
  • 1,339
  • 2
  • 17
  • 32