Cramp and heroku - ruby-on-rails

I have been playing around with Cramp to do some real time pushing of information in an app. Its all working great locally but when I push off to heroku I seem to be having issues with the ports.
I have a socket set up in cramp which inherits from websocket
class LiveSocket < Cramp::Websocket
and I also have a cramp action called home which basically just renders some erb for the home page
class HomeAction < Cramp::Action
in my route file I set up the following and also a static file server
Rack::Builder.new do
puts "public file at #{File.join(File.dirname(__FILE__), '../public')}"
file_server = Rack::File.new(File.join(File.dirname(__FILE__), 'public'))
routes = HttpRouter.new do
add('/').to(HomeAction)
get('/LiveSocket').to(LiveSocket)
end
run Rack::Cascade.new([file_server, routes])
end
Then on the client end the javascript connects to
var ws = new WebSocket("ws://<%= request.host_with_port %>/LiveSocket");
As I say locally it all works. We connect and start receiving notifications from the server. On heroku we run thin on the Cedar stack and have a profile which looks like
web: bundle exec thin --timeout 0 start -p $PORT
When I load up the site the page itself loads fine but on trying to connect the websocket I get an error which says
servername.herokuapp.com Unexpected response code: 200
I am guessing this has something to do with how heroku routes its requests but I do know that you can run a node.js websocket server on heroku so figure there must be a way to get this working too.
Thanks in advance for any help.
cheers
stuart

I don't think Heroku supports websockets :( http://devcenter.heroku.com/articles/http-routing#the_herokuappcom_http_stack

Related

Rails: How to run code when server starts up, but not when running a rake task or the console?

Before, I added code to a file called config/initializers/remote_publishers.rb which set up a connection to RabbitMQ using the Bunny gem on server startup.
However, this is now also executed when running rails c, rails g model SomeModel foo:integer, rails db:migrate etc.
For this app, the RabbitMQ-connection only makes sense when rails is started using rails s(erver).
What is the proper way to conditionally execute this code? Is there a way to see if Rails is starting as server, or only as task-runner?
What web server are you using? On Puma, for example, you can use
on_worker_boot do
# Establish RabbitMQ connection
end
Another possibility might be to check if defined?(Rails::Server) in your initializer: this should only be true when running in the context of the web server.

How can you see your rails server running on heroku, so you can see full output while sending REST requests?

Typically if you use your localhost, you can just run
rails s
from terminal and then when you hit your webserver, you can see the output.
However, when I run
heroku run rails s
and then I hit my webserver up on heroku, I don't get any output like I do when I "rails s" with localhost.
Is there anyway to achieve this?
If you want to see the live server logs, use this command
heroku logs -t
There are many more options available, look at this answer heroku - how to see all the logs
You can use heroku logs command in terminal to see the log just like you see using rails s command.

net/http rails issue works only in console

in ruby on rails console 'net/http' works, but in controller it doesn't and gives timeout error.
require 'net/http'
uri = URI('http://localhost:3000/api_json.json')
json = Net::HTTP.get(uri)
parsed_json = ActiveSupport::JSON.decode(json)
Most likely you're using default Webrick server, that serves one request a time. So, from console it works fine, but fails when you try to call it from controller (when the Webrick worker is already busy).
You can try to setup and run another server like unicorn or thin, or run two Webrick instances on different ports:
rails server
rails server -p 3001
and go to localhost:3001
#dimuch's solution might have solved your issue, but it might help someone facing similar situation. I will explain the issue, and the solution in detail (extension of #dimuch's solution).
Issue:
You might have a controller like some:"/test_controller/test_method", and you might want to call a method in a controller, like /api/v1/some_test_api, and facing error like Completed 500 Internal Server Error in 60004.4ms
[27580c5c46770812c550188346c2dd3e] [127.0.0.1] [/xauth_test/sanity_oauth_login]
Timeout::Error (Timeout::Error):
Solution:
As said by #dimuch, "
Most likely you're using default Webrick server, that serves one request a time.....". 1. You need to run the application on different ports, like
rails s -p 3000, and rails s -p 3001, then make the request from 3001.
If you face an issue like "A server is already running. Check /tmp/pids/server.pid. Exiting", then try running rails s -p 3001 -P PROCESS_ID.
2. Use other server's like Unicorn, or Puma.
Note: If you want it for just testing purpose in local, then I would suggest to go with the first solution, which is easy and simple. I am sorry for poor English, and I found most of solutions from other stack overflow pages, and websites, which I am attaching (links for refs) below, and sorry if I missed some one or some thing to refer. Hope this helps someone.
Refs:
For running multiple instances:
Running multiple instances of Rails Server
Similar errors and way they are handled:
Rails HTTParty Getting Timeout::Error
Faraday timeout error with omniauth (custom strategy)/doorkeeper
Strange Timeout::Error with render_to_string and HTTParty in Controller Action
Configuring Unicorn &Puma:
http://vladigleba.com/blog/2014/03/21/deploying-rails-apps-part-3-configuring-unicorn/
https://github.com/puma/puma

Rails 3.2 PrivatePub in production faye.js not found

I'm having an issue with a gem called private_pub that uses a faye gem and thin server.
This all works fine in development, but on the server I can get everything started up fine but on the page where I'm using private_pub I get an error in the js console (chrome) that says
GET http://myapp.example.com/faye.js 406 (Not Acceptable)
and when I view http://myapp.example.com/faye.js in the browser (url changed) I get an empty screen where in development it displays all the js code. Also I can see in chrome's developer tools I can see in development the type is "Pending" and in production I'm seeing it passed as "text/html"
I've googled and googled and have come up with exactly nothing. Can anyone point me in the right direction.
Is there some special mime-type that is being passed here that I need to configure apache or rails to accept?
Thank you in advance
HAZZAH!
I figured it out.
I jumped through all kinds of hoops and am not 100% sure that the solution I found isn't working because of some of the other things I tried but...
First thing I tried was following a tutorial for installing Thin with a Rails app on Centos, (from Slicehost's docs) Slicehost Articles: CentOS - thin web server for Ruby and did a whole bunch of thin configurations. But I don't believe this was necessary because private_pub/faye is supposed to handle this all for you. (from what I understand)
One important thing is that I know you need to use the startup that private_pub describes, even though you can start thin directly.
RAILS_ENV=production bundle exec rackup private_pub.ru -s thin -D -E production
The '-D' makes sure that it runs as a background process.
In my private_pub.yml:
production:
server: "http://myapp.example.com:9292/faye"
secret_token: "{SECRET_TOKEN HERE}"
signature_expiration: 3600 # one hour
I added in the port# here and it all works now.

Detect if application was started as HTTP server or not (rake task, rconsole etc)

I'm using EventMachine and Monetarily to start e TCP server along with my rails application. This is started from config/initializers/momentarily.rb.
My problem is that it starts also when I run rake tasks, like db:migrate. I only want it to start when when I start the HTTP server. Environments won't help, since both the server start and rake tasks are under Development environment. Is there a way of knowing that the application is running the HTTP server as opposed to anything else? Note that is not only rake tasks, the EM starts also if I run the rails console, which is again something not desirable for my case.
unless File.basename($0) == "rake" && ARGV.include?("db:migrate")
# you are not in rake db:migrate
end
There's not a great way of doing this that I know of. You could copy newrelic's approach (check discover_dispatcher in local_environment.rb) which basically has a list of heuristics used to detect if it is running inside passenger, thin, etc.
For passenger it checks
defined?(::PhusionPassenger)
for thin it checks
if defined?(::Thin) && defined?(::Thin::Server)
Set an environment variable in config.ru file, and use it anywhere in the code to detect if it's executed using a rails server command only.
For e.g.
File: config.ru
ENV['server_mode'] = '1'
And using it somewhere as:
File: config/environment.rb
Thread.new { infinite_loop! }.join if ENV['server_mode'] = '1'
Reference: Answer
Maybe you can implement a switch in the initializer based on ARGV?
Something like:
if ARGV.join(' ').match /something/
# your initializer code here
end
Don't start that other server from an initializer. Create a daemon in script/momentarily and start it from within your app.
After your application launches, you could have it shell out to check ps. If ps shows that the HTTP server is running and the running HTTP server has the same pid as your application (check the pid by inspecting $$), then you could launch the TCP server.
In addition to a great answer by Frederick Cheung above, there can be some other "footprints" in actual process environment. Eg. Phusion Passenger adds certain variables to ENV such as:
PASSENGER_APP_ENV
IN_PASSENGER
PASSENGER_SPAWN_WORK_DIR
PASSENGER_USE_FEEDBACK_FD
Web servers typically can also set SERVER_SOFTWARE variable eg.:
SERVER_SOFTWARE=nginx/1.15.8 Phusion_Passenger/6.0.2

Resources