Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Faye on Heroku in production mode

Rails 4.1.1
Ruby 2.1.1 The access point is https://pacific-savannah-8641.herokuapp.com

Gemfile

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.1'
# Use mysql as the database for Active Record
gem 'mysql2'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer',  platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0',          group: :doc

# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use unicorn as the app server
# gem 'unicorn'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Use debugger
# gem 'debugger', group: [:development, :test]

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin]

gem 'slim-rails'
gem 'devise'
gem 'cancan'
gem 'rakismet'

gem 'carrierwave'
gem 'rmagick', :require => false
gem 'faker', '1.0.1'
gem 'jdbc-mysql', '5.1.28', :platform => :jruby
gem 'thinking-sphinx', '~> 3.1.0'
gem 'remotipart', '~> 1.2'
gem 'kaminari'
gem 'thin'
gem 'carrierwave-aws'

group :production do
  gem 'rails_12factor', '0.0.2'
end

gem 'foreman'
gem 'faye'

faye.ru

require 'faye'
Faye::WebSocket.load_adapter('thin')
faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 45)
run faye_server

application.html.slim

doctype html
html
  head
    title Help Desk App

    = stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true
    = javascript_include_tag "application", "data-turbolinks-track" => true
    = javascript_include_tag  "http://localhost:9292/faye.js"

    = csrf_meta_tags
    ....

Procfile

worker: bundle exec foreman start -f Procfile.workers

Procfile.workers

faye_worker: rackup faye.ru -s thin -E production

app/assets/javascripts/main.js

$(function() {
  var faye = new Faye.Client('http://localhost:9292/faye');
  faye.subscribe('/posts/new', function (data) {
      eval(data);
  });  
}

app/helpers/application_helper.rb

module ApplicationHelper
  def broadcast(channel, &block)
    message = {:channel => channel, :data => capture(&block)}
    uri = URI.parse("http://localhost:9292/faye")
    Net::HTTP.post_form(uri, :message => message.to_json)  
  end
end

heroku ps

drobazko@drobazko:~/www/help_desk$ heroku ps
=== run: one-off processes
run.2182 (1X): up 2015/02/11 08:07:57 (~ 27m ago): `foreman start`

=== web (1X): `bin/rails server -p $PORT -e $RAILS_ENV`
web.1: up 2015/02/11 08:35:44 (~ -40s ago)

=== worker (1X): `bundle exec foreman start -f Procfile.workers`
worker.1: up 2015/02/11 08:35:42 (~ -38s ago)
worker.2: up 2015/02/11 08:35:39 (~ -35s ago)
worker.3: up 2015/02/11 08:35:40 (~ -37s ago)
worker.4: up 2015/02/11 08:35:39 (~ -36s ago)

I couldn't find faye.js: Obviously, the reference http://localhost:9292/faye.js is not accessible.

I have tried to find faye.js without success:

https://pacific-savannah-8641.herokuapp.com/faye.js
https://pacific-savannah-8641.herokuapp.com/faye
http://pacific-savannah-8641.herokuapp.com/faye
http://pacific-savannah-8641.herokuapp.com/faye.js
...http://pacific-savannah-8641.herokuapp.com:9292...

Questions:

How should I replace the reference http://localhost:9292/faye in production on Heroku so that it works?

like image 577
Lesha Pipiev Avatar asked Feb 11 '15 15:02

Lesha Pipiev


1 Answers

I have found the solution.
To use Faye with Heroku without need to add extra dynos (i.e. for free) you should mount Faye to your applications as middleware.
The key point is adding particular lines to application.rb:

require File.expand_path('../boot', __FILE__)

require 'rails/all'
require 'net/http'

Bundler.require(*Rails.groups)

module Helpdesk
  class Application < Rails::Application
    config.middleware.delete Rack::Lock
    config.middleware.use FayeRails::Middleware, mount: '/faye', :timeout => 25
  end
end

Also, you should add faye-rails gem:

gem 'faye-rails', '~> 2.0'

application.js should look as:

//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require jquery.remotipart
//= require turbolinks
//= require faye
//= require_tree .

Then, I have created apps/assets/javascripts/realtime.js.coffee to define how I will handle a realtime messages form server:

window.client = new Faye.Client('/faye')

jQuery ->
  client.subscribe '/comments', (payload) ->
    $('.ticket-' + payload.token + ' .no-posts').remove()

    $('<div></div>')
      .css({'backgroundColor' : '#ff9f5f'})
      .prependTo('.ticket-' + payload.token + ' .posts')
      .hide()
      .append(payload.message)
      .fadeIn('slow')
      .css({transition: 'background-color 3s ease-in-out', "background-color": "white"})

Finally, here is how I publish a message to all subscribers app/views/posts/create.js.coffee:

publisher = client.publish('/comments', {
  message: '<%= j render @post %>',
  token: '<%= @ticket.token %>'
});

Procfile should be with the content:

web: bundle exec rails server thin -p $PORT -e $RACK_ENV

You can check all code out on help_desk

like image 119
Lesha Pipiev Avatar answered Nov 04 '22 08:11

Lesha Pipiev