Can't connect to Redis from Sinatra - ruby

I'm trying to hook up redis to a Sinatra app I'm building:
require 'rubygems'
require 'sinatra'
#require 'sinatra/synchrony'
require 'redis'
require 'mongo_mapper'
require './startup'
def stats_connect
uri = URI.parse('redis://redistogo:xxxxxxxxxxxxxxxxxx#barb.redistogo.com:1337/')
puts 'connecting to... ' + uri.to_s
redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
puts "Statistics connected >> OK" if redis
return redis
end
stats = stats_connect
post('/') do
#...
end
If I run the following app with foreman, I get this error:
18:09:02 web.1 | started with pid 825
18:09:08 web.1 |
/Users/vladdypwnz/.rvm/gems/ruby-1.9.2-p180/gems/redis-3.0.1/lib/redis/connection/ruby.rb:113:in
`connect_nonblock': Can't assign requested address - connect(2)
(Errno::EADDRNOTAVAIL)
18:09:08 web.1 | from
/Users/vladdypwnz/.rvm/gems/ruby-1.9.2-p180/gems/redis-3.0.1/lib/redis/connection/ruby.rb:113:in
`connect'
When I push to heroku, the error changes to this:
/app/vendor/bundle/ruby/1.9.1/gems/redis-3.0.1/lib/redis/client.rb:260:in `rescue in establish_connection': Timed out connecting to Redis on barb.redistogo.com:0 (Redis::CannotConnectError)
If I pop into IRB, require redis and use the same exact stats_connect() method that I created, redis works just fine, I can access everything and create keys.
What's going on? I'm completely stumped.

Are you sure your redis is running on barb.redistogo.com:1337?
A couple weeks ago I deployed an app using redis to heroku and used this configuration:
uri = URI.parse(ENV["REDISTOGO_URL"])
redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
to run it locally I did:
redis = Redis.new(:host => "localhost", :port => 6379)

Related

Can't connect to local MySQL server through socket. I want to connect to REMOTE db

This is my code.
I want to connect to remote database
require 'bundler/setup'
#require "mysql"
#require 'mysql2'
#require "active_record"
Bundler.require
#db_host = ENV["HOST"]
#db_user = ENV["USER"]
#db_pass = ENV['PASSWORD']
#db_name = "db_name"
require "active_record"
ActiveRecord::Base.establish_connection(
:adapter => 'mysql2',
:database => #db_name,
:username => #db_user,
:password => #db_pass,
:host => #db_host)
class ConversionRate < ActiveRecord::Base
end
class ConversionRateMonthly < ActiveRecord::Base
self.table_name = "conversion_rates_monthly"
end
class KdpReport < ActiveRecord::Base
end
class SalesCalculator
def run
p KdpReport.count
end
end
calculator = SalesCalculator.new
calculator.run
But I get this error:
/home/jonsdirewolf/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/mysql2-0.4.9/lib/mysql2/client.rb:89:in `connect': Can't connect to local MySQL server through socket
'/var/run/mysqld/mysqld.sock' (2) (Mysql2::Error)
It is strange but yesterday my code worked. what may be wrong? I want to connect to remote db, not local. And btw I use ruby without rails.
So, the problem is in empty environment var ENV["HOST"].
When host, passed to ActiveRecord is nil or equl to string localhost - AR will try to connect to db using socket.

sending file with pony by sinatra app - missing file

I want to send a email from my sinatra application.
Here is the code:
require 'pony'
class Cms < Application
get "/mail" do
Pony.mail :to => 'to#gmail.com',
:from => "from#gmail.com",
:subject => "Thanks for signing my guestbook!",
:via => :sendmail,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:user_name => 'user#gmail.com',
:pass => 'pass',
:enable_starttls_auto => false
},
:body => erb(:"cms/mail")
redirect '/'
end
end`
Thin is starting application with no errors, but When i request myapp.local/mail i've got an error:
LoadError - no such file to load -- mail/network/delivery_methods/smtp:
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/configuration.rb:31:in lookup_delivery_method'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/configuration.rb:25:in delivery_method'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/mail.rb:111:in delivery_method'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/message.rb:116:in initialize'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/mail.rb:50:in new'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/mail.rb:50:in new'
/var/lib/gems/1.8/gems/pony-1.4/lib/pony.rb:174:in build_mail'
/var/lib/gems/1.8/gems/pony-1.4/lib/pony.rb:138:in mail'
./app/controllers/cms.rb:8:in GET /mail'
File /var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/network/delivery_methods/smtp.rb exists.
I was getting this same error when I was using the inline configuration of the Mail gem:
mail.delivery_method :sendmail
mail.deliver!
Removing that first line, and moving the configuration to immediately following the loading of the mail gem fixed it.
Wherever in your app you require 'mail' just configure it immediately:
require 'mail'
Mail.defaults do
delivery_method :sendmail
end
Update: This worked for awhile... But then for some reason I began seeing this error:
rbenv/versions/1.8.7-p374/lib/ruby/gems/1.8/gems/mail-2.5.4/lib/mail/fields/common/common_address.rb:9:in `parse': no such file to load -- mail/elements/address_list (LoadError)
Update2: The failures happen randomly it seems. Something about the way the autoload works in Ruby 1.8.7-p374 is causing it to not be able to find files that do in fact exist. Also, I am using slimgems not rubygems.
These are the hacks I've had to implement so far to use Mail with multi-part email and sendmail delivery method:
require 'mail'
require 'mail/network/delivery_methods/sendmail'
require 'mail/elements/address_list'
require 'mail/fields/common/common_address'
require 'mail/elements/content_type_element'
require 'mail/elements/address'
require 'mail/elements/content_transfer_encoding_element'
Mail.defaults do
delivery_method :sendmail
end

Sinatra/ActiveRecord can't handle simultaneous requests?

This is my first Sinatra project and I'm pretty late in and I'm realizing that when make multiple requests at once that use ActiveRecord that I run into problems. If I only make one request, each one works on its own. But when I call both at once, I get failure.
So far I've narrowed it down to the problem being two ActiveRecord requests simultaneously. Maybe I'm not setting up ActiveRecord correctly? I use PostgreSQL because Heroku uses it, and am no inclined to change. (The issue happens on Heroku, too.)
Here's the log:
192.168.1.113 - - [30/Sep/2012:10:33:00 MDT] "GET /version/current?platform=android HTTP/1.1" 200 33
- -> /version/current?platform=android ActiveRecord::StatementInvalid - NoMethodError: undefined method `fields' for nil:NilClass: SELECT "rankings".* FROM "rankings" WHERE "rankings"."user_id" = 1 LIMIT 1:
/Users/zablanc/.rvm/gems/ruby-1.9.3-head#emm/gems/activerecord-3.2.7/lib/active_record/connection_adapters/postgresql_adapter.rb:667:in `block in exec_query'
...
Warning! Rack::Session::Cookie data size exceeds 4K.
Warning! Rack::Session::Cookie failed to save session. Content dropped.
192.168.1.113 - - [30/Sep/2012:10:33:01 MDT] "GET /badges/all HTTP/1.1" 200 311
- -> /badges/all
192.168.1.113 - - [30/Sep/2012:10:33:01 MDT] "GET /moves/ranking/all HTTP/1.1" 500 166185
- -> /moves/ranking/all
I have no idea how to shut up those cookie warnings, tho they seem to have no effect on the app. Here's how I configure my app (in a config file I require from the main script):
enable :logging
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use Rack::Session::Cookie, :key => 'rack.session',
:path => '/',
:expire_after => 31_536_000, # In seconds
:secret => 'jeowkfj...secret...kjn5'
ActiveRecord::Base.include_root_in_json = false
def establish_connection(url)
db = URI.parse(url)
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:port => db.port,
:username => db.user,
:password => db.password,
:database => db.path[1..-1],
:encoding => 'utf8'
)
end
configure :development do
establish_connection('postgres://postgres:postgres#localhost:5432/emm')
end
configure :test do
establish_connection('postgres://postgres:postgres#localhost:5432/emm-test')
end
configure :production do
establish_connection(ENV['DATABASE_URL'])
end
I'm guessing I'm not setting up ActiveRecord right, but I think it's just like the tutorials I've seen. What gives?
Sounds like you are using threads but have some non-thread-safe code in your application.
Which webserver are you using, which middleware are you using, which postgresql gem are you using, did you check to see that all your gems are thread-safe?

using redis and ruby to implement a tiny short url app

I'm making a short URL app, using Ruby, Sinatra, and Redis. Currently it's under 15 lines:
require 'rubygems'
require 'sinatra'
require 'redis'
require 'uri'
configure do
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
get '/' do
haml :index
end
post '/shorten' do
a = rand(9999)
REDIS.set(a.to_s, params[:long])
"<pre>http://199.19.118.186/get/#{a}</pre>"
#haml :shorten
end
get '/get/:url' do
redirect REDIS.get(params[:url])
end
Where index.haml is a form that POSTs long to /shorten. I've no problem with that.
Right now, however, when I try to use Redis (with the server running, yes), I get this error:
What am I doing wrong?
EDIT: Copy/paste from Emacs... facepalm
EDIT: When trying to access redis alone from ruby (code below), I get this:
/var/lib/gems/1.8/gems/redis-2.2.2/lib/redis/client.rb:47:in `call': ERR unknown command (RuntimeError)
from /var/lib/gems/1.8/gems/redis-2.2.2/lib/redis.rb:841:in `set'
from /usr/lib/ruby/1.8/monitor.rb:242:in `synchronize'
from /var/lib/gems/1.8/gems/redis-2.2.2/lib/redis.rb:840:in `set'
from test_redis.rb:9
With this code:
require 'rubygems'
require 'redis'
require 'uri'
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
REDIS.set("test", "blah")
puts REDIS.get("test")
Ruby being case sensitive, I would try to replace REDIS.SET by REDIS.set and REDIS.GET by REDIS.get. You can find the documentation of the Redis client here:
https://github.com/ezmobius/redis-rb
I have tested your example with ruby 1.8.7. (default on my Linux box).
After installing sinatra, haml, redis and hiredis gems, I have modified the code as follows:
require 'rubygems'
require 'sinatra'
require 'redis'
require 'uri'
configure do
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
get '/' do
"Hello"
haml :index
end
post '/shorten' do
a = rand(9999)
REDIS.set(a.to_s, "http://"+params[:long])
"<pre>http://localhost:4567/get/#{a}</pre>"
end
get '/get/:url' do
redirect REDIS.get(params[:url])
end
I have added the following template in views/index.haml.
!!!
%html
%head
%title My Sinatra Website
%body
%h1 Welcome
%p
Welcome to my website made with Sinatra and HAML
%form{ :action => "/shorten", :method=>"POST" }
%fieldset
%input{ :type =>"text", :name=>"long" }
%input{ :type =>"submit" }
Once Redis is started on port 6379 and sinatra on port 4567, it works like a charm.
I suggest you check your ruby installation and try to access Redis from ruby with a simple non sinatra script.
UPDATE:
The error message is peculiar because normally, when an unknown command is sent to the server, the faulty command is provided:
ERR unknown command 'dummy'
while you just have:
ERR unknown command
Actually, this specific fix was introduced in Redis server more than 2 years ago (in December 2009) - an eternity for Redis.
https://github.com/antirez/redis/commit/2c14807b2dd5c15f1471bec32a7c6dbb077720ee
In other words, you are trying to use a very old (i.e. pre 1-3) version of Redis server with the last version of the Redis client ruby gem, which probably does not support anymore the initial protocol. You may want to compile and install a recent version of Redis server (it is easy), it should work better.

net-ssh and ActiveRecord 3: bringing it all together

I'm working on a small Ruby program that will connect to a remote MySQL Bugzilla database, perform a query of records, and email details of those records to a group on a daily basis.
So far, I've been able to SSH to the db server and execute a command using net-ssh. Here's an example:
require 'net/ssh'
Net::SSH.start("db.example.com", "sroach", :password => "secret") do |ssh|
result = ssh.exec!("ls -l")
puts result
end
That outputs just fine.
Using ActiveRecord 3.0.3, I wanted to test the establish_connection method so I established a connection to my local MySQL database and was able to execute commands using ActiveRecord. Example:
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:database => "list_tool_development",
:username => "my_username",
:password => "secretpassword"
)
class MailingList < ActiveRecord::Base
end
MailingList.first #=> Successfully retrieves first record from the table
So, where I'm having trouble is bringing it all together and applying it to my remote MySQL db. Here's my best try thus far:
require 'net/ssh'
Net::SSH.start("db.example.com", "sroach", :password => "secret") do |ssh|
ssh.forward.local(3307, "127.0.0.1", 3306)
ssh.loop { true }
end
But all that does is make my IRB session hang (which could be completely normal...don't know). Incase that hang was normal, I opened a new IRB session and tried to establish a connection to the remote database like so:
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "127.0.0.1",
:port => 3307,
:reconnect => false,
:database => "bugs",
:pool => 5,
:username => "my_username",
:password => "secret",
:socket => "/tmp/mysql.sock"
)
class Bug < ActiveRecord::Base #=> the table name in the "bugs" db is "bugs"
end #=> so I made the model singular
Bug.first #=> the IRB session hangs at this point
So, I have no idea what's going wrong or how to degub it. Any and all suggestions would be helpful.
I'm on Mac OSX. The db that I'm trying to connect to is on FreeBSD 7.0 and is MySQL version Ver 14.12 Distrib 5.0.67.
Rather than try to tunnel the ActiveRecord connection inside SSH, have you tried connecting directly from ActiveRecord to the DB server? That is the normal way to connect across a network and is directly supported by ActiveRecord.
Replace the host ID with the server host IP or DNS entry, the port can probably be allowed to default to the MySQL driver's default of 3306, and the socket isn't needed since the DB is on the remote host.
If the DB host isn't on the same network as yours, and you're crossing firewalls, you might need to have that port opened to allow the connection. If it is on the same network it should work without needing ssh at all.

Resources