Automatically Refreshing Rails Metal In Development Mode - ruby-on-rails

I am trying to develop a rails metal endpoint using sinatra, but is proving to be a pain because I have to restart the server every time I change the code. I am in Jruby and running from within a larger Java app. Is there an easy way to make this code refresh for every request?

Just because I like abstract abstraction, this is Ryan's code v2:
def every s
loop do
sleep s
yield
end
end
every 1 { `touch tmp/restart.txt` }

I don't think there is a way to automatically reload sinatra code, however:
If you were running passenger, you could try running in irb:
loop do
`touch tmp/restart.txt`
sleep(1)
end
Which will then tell the passenger instance to restart the application.

Related

Improve concurrency on a simple AJAX call in rails

I have created a simple ajax call with the following code:
controller.rb
def locations
sleep 1.2
some_data = [{"name"=> "chris", "age"=> "14"}]
render json: some_data
end
view.js
function getLocation() {
$.get('/location').success(function(data){console.log(data);});
}
$(".button").click(function() {getLocation();});
Routes.rb
get '/location' => 'controller#locations'
Note that the sleep 1.2 in the controller it is to prevent doing background jobs or database calls.
The screenshot below is from the devtools Network tab, it shows I have clicked the button 8 times and all the subsequent calls are stalled until the previous action is finished. I think it is due to Rails being single threaded? Will it be a different case if the server is made with NodeJS? And How can I achieve similar concurrency with Rails for similar AJAX calls?
Thanks!!
Actually, it is not due to Rails, but to the Rails server you are using. Some are single threaded, and others can be launched as multithreaded.
For instance, if you use Phusion passenger, you can configure it to run using several threads and so to improve the concurrency. You should look for Rails "server" comparisons instead of trying to find a solution or a problem with the Rails "framework".
Popular servers are Thin, Unicorn, Puma, Phusion passenger. The default development server is call Webrick.
There are a lot of other stackoverflow questions relating to the differences between servers so I think you should look into them.

How to Use Resque Web alongside a Sinatra app

I’ve got a Sinatra web app. I’m using Resque and Resque Scheduler, and now I’m looking into adding Resque Web to (hopefully) see what my Resque queue looks like. Now here’s my problem: the official Resque Web is a Rails app. I don’t know how to use a Rails app inside of Sinatra, or if it’s even possible.
So my question: What’s the best way to implement Resque Web into my Sinatra app? Can I use the rails app inside of Sinatra? I saw one person say that you should have a separate part of your app running Rails, but that seems really nasty. Is there a better way to do it?
Thanks!
I've not used the ResqueWeb, but Rails and Sinatra are both Rack compliant frameworks, so they should be able to run each other or alongside.
http://www.sinatrarb.com/intro.html#Rack%20Middleware
## my-amazing-app.rb
use MySlightlyLessAmazingRailsApp
# rest of Sinatra stuff…
or
# config.ru
map "/" do
# easiest to mount Sinatra apps this way if using the modular style
run MyAmazingSinatraApp
end
map "/resque" do
run MySlightlyLessAmazingRailsApp
end
I don't know how you'd do this with Rails, perhaps try this link http://m.onkey.org/rails-meets-sinatra or perhaps this:
RailsApp::Application.routes.draw do
mount MyAmazingApp, :at => "/more-amazed"
# rest of the rails routes
end
Here’s what I was looking for: http://asciicasts.com/episodes/271-resque
Resque-web can be stand alone, run from the command line. So I’m just starting it up with a shell command whenever I spin up an instance of my server. Not exactly what I was looking for, but it does the trick!
Thanks for the suggestions, all.

Launch a script on a separate server from a Rails app

In my Rails app, when a user clicks a button it will currently launch an in-house created script in the background. For simplicity, let's just call it myScript. So in my Rails app, I basically have:
def run!
`myScript with some arguments`
end
Now this script will run as a process on the same machine that the Rails application is running on.
We want to host all of our Ruby/Rails apps on one server, and utilize a separate server for running the scripts. Is it possible to launch that script, but on a different machine? Let me know if you need additional information.
I use ssh for these types of things.
require 'net/ssh'
Net::SSH.start('server.com', 'username', password: "asdasd") do |ssh|
$stdout.print ssh.exec!("cdc && curl https://gist.github.com/mhenrixon/asdasd123123/raw/123123asdasd/update.rb | rails c production")
end
That's the easiest way of doing it I think but the sinatra/rails listener isn't a bad idea either.
To flat out steal Dogbert's answer: I'd go with a HTTP solution. Create a background job (Sidekick, Queue Classic) and have a simple job that does a get or a post or whatever on that second server.
The HTTP solution will involve a bit of a setup cost (time and learning probably) but in the end it will be a bit more robust than the SSH solution as you won't have to worry about IPs or users,etc. just a straight up URL. Plus if you are doing things with Capistrano,etc your deployments will be super easy.
Is there a reason why these jobs couldn't be run on the your webserver, but with a background process?

em-websocket gem with Ruby on Rails

I started developing a web-socket based game using the em-websocket gem.
To test the application I start the server by running
$> ruby server.rb
and then I just open two browsers going directly to the html file (no web server) and start playing.
But now I want to add a web server, some database tables, an other Ruby on Rails based gems.
How an achieve communication between my web-socket server and my Ruby on Rails application? Should they run in the same server and run as a single process? Run in separate servers and communicate through AJAX?
I need to support authentication and other features like updating the database when a game is finished, etc.
Thanks in advance.
There is an issue created about this:
https://github.com/igrigorik/em-websocket/issues/21
Here is the deal. I also wanted to develop a websocket server client with ruby on rails framework. However ruby-on-rails is not very friendly with eventmachine. I have struggeled with having a websocket client, so I managed to copy/cut/paste with from existing lib, and end up with the following two escessential ones.
Em-Websocket server
https://gist.github.com/ffaf2a8046b795d94ba0
ROR friendly websocket client
https://gist.github.com/2416740
have the server code in script directory, the start like the following in ruby code.
# Spawn a new process and run the rake command
pid = Process.spawn("ruby", "web_socket_server.rb",
"--loglevel=debug", "--logfile=#{Rails.root}/log/websocket.log",
:chdir=>"#{Rails.root}/script") #,
:out => 'dev/null', :err => 'dev/null'
Process.detach pid # Detach the spawned process
Then your client can be used like this
ws = WebSocketClient.new("ws://127.0.0.1:8099/import")
Thread.new() do
while data = ws.receive()
if data =~ /cancel/
ws.send("Cancelling..")
exit
end
end
end
ws.close
I wish there is a good ROR friendly em-websocket client, but couldn't fine one yet.
Once you made server/client works well, auth. and database support must not be very different from other rails code. (I mean having client side with some auth/db restrictions)
I am working on a gem that may be helpful with your current use case. The gem is called websocket-rails and has been designed from the ground up to make using WebSockets inside of a Rails application drop dead simple. It is now at a stable release.
Please let me know if you find this helpful or have any thoughts on where it may be lacking.

how to run multiple nokogiri screen scrape threads at once

I have a website that requires using Nokogiri on many different websites to extract data. This process is ran as a background job using the delayed_job gem. However it takes around 3-4 seconds per page to run because it has to pause and wait for other websites to respond.
I am currently just running them by basically saying
Websites.all.each do |website|
# screen scrape
end
I would like to execute them in batches rather than one each so that I dont have to wait for a server response from every site (can take up to 20 seconds on occassion).
What would be the best ruby or rails way to do this?
Thanks for your help in advance.
You might want to check out Typhoeus which enables you to make parallel http requests.
I found a short blawg post here about using it with Nokogiri, but I haven't tried this myself.
Wrapped in a DJ, this should do the trick with little client-side latency.
You need to use delayed job. Check out this Railscasts.
Keep in mind most hosts charge for this type of thing.
You can also use the spawn plugin if you don't care about managing threads but it is much much easier!!!
This is literally all you need to do:
rails plugin/install https://github.com/tra/spawn.git
Then in your controller or model add the method
For example:
spawn do
#execute your code here :)
end
http://railscasts.com/episodes/171-delayed-job
https://github.com/tra/spawn
I'm using EventMachine to do something similar to this for a current project. There is a terrific plugin called em-http-request that allows you to make mutliple HTTP requests in parallel, as well as providing options for synchronising the responses.
From the em-http-request github docs:
EventMachine.run {
http1 = EventMachine::HttpRequest.new('http://google.com/').get
http2 = EventMachine::HttpRequest.new('http://yahoo.com/').get
http1.callback { }
http2.callback { }
end
So in your case, you could have
callbacks = []
Websites.all.each do |website|
callbacks << EventMachine::HttpRequest.new(website.url).get
end
callbacks.each do |http|
http.callback { }
end
Run your rails application with the thin webserver in order to get a functioning EventMachine loop:
bundle exec rails server thin
You'll also need the eventmachine and em-http-request gems. Good luck!

Resources