How to start faye automatically using daemon-controller? - ruby-on-rails

I am trying to run faye automatically using gem daemon_controller.
My Class
require "daemon_controller"
class FayeDaemon
def initialize
#controller = DaemonController.new(
:identifier => 'Faye server',
:start_command => "rackup faye.ru -s thin -E production",
:ping_command => [:tcp , 'localhost', 9292],
:log_file => 'log/faye.log',
:pid_file => 'tmp/pids/faye.pid',
:start_timeout => 5
)
end
def start
#controller.start
end
end
Function I use as before_filter in ApplicationController
def start_faye
fayes = FayeDaemon.new
fayes.start
end
as a result faye doesn't run with error
DaemonController::StartTimeout (Daemon 'Faye server' didn't daemonize in time.)
when fayes.start is called.
what i did wrong?

I highly recommend you to use foreman instead of deamon_controller, you can find good introduction here. Just install gem, create 'Procfile' in your rails root directory. and create two jobs, one for server and other for Faye, it could look like this:
web: bundle exec rails server webrick -b 127.0.0.1 -p 3000 -e development
faye: bundle exec rackup faye.ru -s thin -E production
and start foreman with
foreman start

Related

Faye Messaging on Heroku

I keep getting a 503 error 30 seconds after a client sends a message through faye. After the 30 seconds the client then receives the message and it is appended to the chat but the error still occurs and the socket will eventually close. How can i modify my existing code to keep the websocket alive? And how can I get rid of the 30 second delay that heroku throws when a message is sent?
messages/add.js.erb
<% broadcast #path do %>
var $chat = $("#chat<%= #conversation.id %>");
$chat.append("<%= j render(#message) %>");
//Set the scroll bar to the bottom of the chat box
var messageBox = document.getElementById('chat<%= #conversation.id %>');
messageBox.scrollTop = messageBox.scrollHeight;
<% end %>
$("#convoId<%=#conversation.id%>")[0].reset();
application_helper.rb
def broadcast(channel, &block)
message = {:channel => channel, :data => capture(&block), :ext => {:auth_token => FAYE_TOKEN}}
uri = URI.parse(FAYE_END_PT)
Net::HTTP.post_form(uri, :message => message.to_json)
end
application.rb
config.middleware.delete Rack::Lock
config.middleware.use FayeRails::Middleware, mount: '/faye', :timeout => 25
faye.ru
require 'faye'
require File.expand_path('../faye_token.rb', __FILE__)
class ServerAuth
def incoming(message, callback)
if message['channel'] !~ %r{^/meta/}
if message['ext']['auth_token'] != FAYE_TOKEN
message['error'] = 'Invalid authentication token'
end
end
callback.call(message)
end
end
Faye::WebSocket.load_adapter('thin')
faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 45)
faye_server.add_extension(ServerAuth.new)
run faye_server
Procfile
web: bundle exec rails server -p $PORT
worker: bundle exec foreman start -f Procfile.workers
Procile.workers
faye_worker: rackup middlewares/faye.ru -s thin -E production
503 Error
/messages/add Failed to load resource: the server responded with a status of 503 (Service Unavailable)
I tried adding a worker to heroku along with a web dyno with no luck. Everything works fine on my local host when running heroku local. The process on the local host look like
forego | starting web.1 on port 5000
forego | starting worker.1 on port 5100
worker.1 | 20:33:18 faye_worker.1 | started with pid 16534
where as even with the web dyno and worker on heroku
=== web (1X): bundle exec rails server -p $PORT
web.1: up 2015/12/28 20:08:02 (~ 1h ago)
=== worker (1X): bundle exec foreman start -f Procfile.workers
worker.1: up 2015/12/28 21:18:39 (~ 40s ago)
A lot of this code was taken from various tutorials so hopefully if we can solve this issue it will make using Faye with Heroku easier to someone else as well. Thanks!
Heroku has a 30 seconds timeout for all the requests, after that raise an H12 error. https://devcenter.heroku.com/articles/limits#http-timeouts
If your request takes more that 30 seconds you should consider put it into a background job using Delayed_Job or Sidekiq for example.

How to use thor in rails?

Thor is a toolkit for building powerful command-line interfaces.
It always been used for single command line. If I want to use it in a rails project, for example:
lib/tasks/my_cli.rb
require "thor"
class MyCLI < Thor
desc "hello NAME", "say hello to NAME"
def hello(name)
puts "Hello #{name}"
end
end
Where to put the MyCLI.start(ARGV)?
If I put it under that file(lib/tasks/my_cli.rb), when I run my rspec test, it will show me the command message:
Commands:
rspec help [COMMAND] # Describe available commands or one specific command
rspec hello NAME # say hello to NAME
I don't want to see it in my bundle exec rspec, so I moved the MyCLI.start(ARGV) to bin/rails. It looks well. But after I do this:
$ ./bin/rails s -b 0.0.0.0
$ [CTRL+C]
I saw this message:
=> Booting Thin
=> Rails 4.2.0 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 0.0.0.0:3000, CTRL+C to stop
^CStopping ...
Exiting
Could not find command "_b".
What does it mean:
Could not find command "_b".
So, I don't know a best practice about how to use thor in a rails project.
You have to use method_option:
https://github.com/erikhuda/thor/wiki/Method-Options
And don't pass arguments like if it would be a normal method
require "thor"
class MyCLI < Thor
desc "hello NAME", "say hello to NAME"
method_option :name, aliases: '-b', type: :string, desc: 'It`s the named passed'
def hello
puts "Hello #{options[:name]}"
end
end
Then use it with thor command:
thor mycli:hello -b Robert

Whenever gem on aws opsworks

Does anyone have experience/success using the whenever gem on aws opsworks? Is there a good recipe? Can I put that recipe on a separate layer and associate one instance with that additional layer? Or is there a better way to do it? Thanks!!!
EDIT:
We ended up doing it a bit differently...
Code:
Can’t really post the real code, but it’s like this:
in deploy/before_migrate.rb:
[:schedule].each do |config_name|
Chef::Log.info("Processing config for #{config_name}")
begin
template "#{release_path}/config/#{config_name}.rb" do |_config_file|
variables(
config_name => node[:deploy][:APP_NAME][:config_files][config_name]
)
local true
source "#{release_path}/config/#{config_name}.rb.erb"
end
rescue => e
Chef::Log.error e
raise "Error processing config for #{config_name}: #{e}"
end
end
in deploy/after_restart.rb:
execute 'start whenever' do
cwd release_path
user node[:deploy][:APP_NAME][:user] || 'deploy'
command 'bundle exec whenever -i APP_NAME'
end
in config/schedule.rb.erb:
<% schedule = #schedule || {} %>
set :job_template, "bash -l -c 'export PATH=/usr/local/bin:${PATH} && :job'"
job_type :runner, 'cd :path && bundle exec rails runner -e :environment ":task" :output'
job_type :five_runner, 'cd :path && timeout 300 bundle exec rails runner -e :environment ":task" :output'
set :output, 'log/five_minute_job.log'
every 5.minutes, at: <%= schedule[:five_minute_job_minute] || 0 %> do
five_runner 'Model.method'
end
We have a whenever cookbook in our repo we use that you would be more than welcome to use here: https://github.com/freerunningtech/frt-opsworks-cookbooks. I assume you're familiar with adding custom cookbooks to your opsworks stacks.
We generally run it on its own layer that also includes the rails cookbooks required for application deployment (while not the app server):
Configure: rails::configure
Deploy: deploy::rails whenever
Undeploy: deploy::rails-undeploy
However, we usually also deploy this instance as an application server, meaning we do end up serving requests from the box we're using for whenever as well.
There is one "gotcha", in that you must set your path in the env at the top of the schedule.rb like this:
env :PATH, ENV['PATH']

rails 3.1 Whenever gem works in development but not in production. Why?

Rails 3.1 + Whenever gem.
I've got 2 jobs scheduled in Whenever. However, apparently nothing happens.
I have tried these methods through Heroku console, and they work. So I reckon that they do not get fired at any point. Am I missing something?
config/schulde.rb
every 1.day, :at => '03:30' do
runner "Alarm.proba"
end
every 1.day, :at=> '3:32 am' do
runner "Alarm.proba2"
end
Alarm model
def self.proba
#event = Event.find(10)
#user =User.find(12)
EventNotifier.alarm(#event, #user).deliver
end
def self.proba2
#event = Event.find(10)
#user =User.find(13)
EventNotifier.alarm(#event, #user).deliver
end
$ crontab -l
# Begin Whenever generated tasks for: quasi
5 4 * * * /bin/bash -l -c 'cd /Users/sergioabendivar/railsProjects/Tutos/quasi && script/rails runner -e production '\''Alarm.proba'\'''
5 4 * * * /bin/bash -l -c 'cd /Users/sergioabendivar/railsProjects/Tutos/quasi && script/rails runner -e production '\''Alarm.proba2'\'''
I assume that it woks in development because my console now says "You have an email". Actually if I check the email I got quite a lot.
Use Heroku Scheduler instead: https://devcenter.heroku.com/articles/scheduler

How to change Rails 3 server default port in develoment?

On my development machine, I use port 10524. So I start my server this way :
rails s -p 10524
Is there a way to change the default port to 10524 so I wouldn't have to append the port each time I start the server?
First - do not edit anything in your gem path! It will influence all projects, and you will have a lot problems later...
In your project edit script/rails this way:
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
# THIS IS NEW:
require "rails/commands/server"
module Rails
class Server
def default_options
super.merge({
:Port => 10524,
:environment => (ENV['RAILS_ENV'] || "development").dup,
:daemonize => false,
:debugger => false,
:pid => File.expand_path("tmp/pids/server.pid"),
:config => File.expand_path("config.ru")
})
end
end
end
# END OF CHANGE
require 'rails/commands'
The principle is simple - you are monkey-patching the server runner - so it will influence just one project.
UPDATE: Yes, I know that the there is simpler solution with bash script containing:
#!/bin/bash
rails server -p 10524
but this solution has a serious drawback - it is boring as hell.
I like to append the following to config/boot.rb:
require 'rails/commands/server'
module Rails
class Server
alias :default_options_alias :default_options
def default_options
default_options_alias.merge!(:Port => 3333)
end
end
end
One more idea for you. Create a rake task that calls rails server with the -p.
task "start" => :environment do
system 'rails server -p 3001'
end
then call rake start instead of rails server
Combining two previous answers, for Rails 4.0.4 (and up, presumably), this suffices at the end of config/boot.rb:
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge({Port: 10524})
end
end
end
We're using Puma as a web server, and dotenv to set environment variables in development. This means I can set an environment variable for PORT, and reference it in the Puma config.
# .env
PORT=10524
# config/puma.rb
port ENV['PORT']
However, you'll have to start your app with foreman start instead of rails s, otherwise the puma config doesn't get read properly.
I like this approach because the configuration works the same way in development and production, you just change the value of the port if necessary.
Inspired by Radek and Spencer...
On Rails 4(.0.2 - Ruby 2.1.0 ), I was able to append this to config/boot.rb:
# config/boot.rb
# ...existing code
require 'rails/commands/server'
module Rails
# Override default development
# Server port
class Server
def default_options
super.merge(Port: 3100)
end
end
end
All other configuration in default_options are still set, and command-line switches still override defaults.
Solution for Rails 2.3 - script/server:
#!/usr/bin/env ruby
require 'rack/handler'
module Rack::Handler
class << WEBrick
alias_method :old_run, :run
end
class WEBrick
def self.run(app, options={})
options[:Port] = 3010 if options[:Port] == 3000
old_run(app, options)
end
end
end
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/server'
If you're using puma (I'm using this on Rails 6+):
To change default port for all environments:
The "{3000}" part sets the default port if undefined in ENV.
~/config/puma.rb
change:
port ENV.fetch('PORT') { 3000 }
for:
port ENV.fetch('PORT') { 10524 }
To define it depending on the environment, using Figaro gem for credentials/environment variable:
~/application.yml
local_db_username: your_user_name
​local_db_password: your_password
PORT: 10524
You can adapt this to you own environment variable manager.
You could install $ gem install foreman, and use foreman to start your server as defined in your Procfile like:
web: bundle exec rails -p 10524
You can check foreman gem docs here: https://github.com/ddollar/foreman for more info
The benefit of this approach is not only can you set/change the port in the config easily and that it doesn't require much code to be added but also you can add different steps in the Procfile that foreman will run for you so you don't have to go though them each time you want to start you application something like:
bundle: bundle install
web: bundle exec rails -p 10524
...
...
Cheers
For ruby > 3 and For rails > 7
in file app/config/puma.rb, update the port number.
port ENV.fetch("PORT") { 3200 }

Resources