Search code examples
ruby-on-rails-3zxingproduction-environment

Zxing connection refused on production


I'm using ZXing to decode my qr codes, it works fine on development, but on production after deploy it just works for five minutes or so and only if I restart the server, after that it just doesn't work, going through the log, this is what comes out:

ActionView::Template::Error (druby://127.0.0.1:51876 - #<Errno::ECONNREFUSED: Connection refused - connect(2)>):
1: <% provide(:title, "Updating...") %>
2: <input />
3: <% if (ZXing.decode "public/assets/#{current_user.user_name.downcase}_bdd.jpg").nil? %>
4:  <% flash.now[:notice] = "BDD invalid, change it!" %>
5:  <div class="actions_cambiar_bdd">
app/views/users/change_folios.html.erb:3:in 
`_app_views_users_change_folios_html_erb___206747123981808960_69821004639000'

I don't know what is going on, looking at it, I think that it cannot works its way out to my server that's why the connection refused, but the weird thing is that it works fine for a couple of minutes after the server is restarted, after that, nothing, I hope anyone can help me out. Thanks for your time.

EDIT: Apparently after a while the port gets blocked or busy, i guess that is something to do with how zxing manage the port assign, here are some files of it:

EDIT 2

client.rb

require 'socket'
require 'drb'

module ZXing
  BIN = File.expand_path('../../../bin/zxing', __FILE__)

  class Client
    def self.new
      port = ENV['ZXING_PORT'] || find_available_port
      setup_drb_server(port) unless ENV['ZXING_PORT'] && responsive?(port)
      DRbObject.new_with_uri("druby://127.0.0.1:#{port}")
    end

    private

    def self.setup_drb_server(port)
      remote_client = IO.popen("#{ZXing::BIN} #{port}")
      sleep 0.5 until responsive?(port)
      at_exit { Process.kill(:INT, remote_client.pid) }
    end

    def self.responsive?(port)
      socket = TCPSocket.open('127.0.0.1', port)
      true
    rescue Errno::ECONNREFUSED
      false
    ensure
      socket.close if socket
    end

    def self.find_available_port
      server = TCPServer.new('127.0.0.1', 0)
      server.addr[1]
    ensure
      server.close if server
    end
  end
end

I kind of get answered on github by one of the guys in the zxing project:

https://github.com/ecin/zxing.rb/issues/6

Shortly he gave me the advice to export from my code the ZXING_PORT const, but it did not solve it, the number on the ZXING_PORT gets the same treatment, it works for a couple of minutes, and then the same mistake, only this time with the ZXING_PORT

ActionView::Template::Error (druby://127.0.0.1:ZXING_PORT - #<Errno::ECONNREFUSED: Connection refused - connect(2)>):

I'm considering the options to either somehow "reserve" the port or socket so no process can take it or find a way to reload the gem on the production environment on every request.

Which option should i take? Which one is the more appropied or the more plausible?


Solution

  • Ok, so i finally got it to work, i put the code on boot.rb, just before the gems are loaded

    require 'rubygems'
    
    # Set up gems listed in the Gemfile.
    ENV['PORT_NUMBER'] = "4333"
    ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
    
    
    require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])