Sha256: bd64460a57378cdf7cc8e54cf013ec41084d399f242166c8e4bfbf52990b7381

Contents?: true

Size: 1.73 KB

Versions: 1

Compression:

Stored size: 1.73 KB

Contents

# managing connection across forks and threads is tricky.  most libraries use
# and icky idiom that requires each and every client to configure it's own
# forking logic, something like
#
#   MyLameLib.after_for do
#     # close handles you should close
#   end
#
# many libs also do not provide you with per-thread connection, making MT a
# manual process.
#
# a teeny bit of code can solve both.  the concept is simple:
#
# maintain a table of connections scoped by process id and thread id.  any
# miss will trigger auto-scrubbing the table, but only connections from
# another process (we've been forked) will be closed.  this gives
#
# * per thread connections
#
# * per process connections
#
# * auto-matic cleanup after a fork
#
module ForkHandle
  def version
    '0.0.1'
  end

  @handles = Hash.new
  @pid = Process.pid
  @tid = Thread.current.object_id

  attr_accessor :handles
  attr_accessor :pid
  attr_accessor :tid

  class Key
    def for(*args)
      case
        when args.size == 1 && args.first.is_a?(Key)
          args.first
        else
          new(*args)
      end
    end

    def initialize(pid, tid, key)
      @pid = pid
      @tid = tid
      @key = key
    end
  end

  def key_for(key)
    Key.for(@pid, @tid, key)
  end

  def get(key, &block)
    @handles.fetch(key_for(key)) do
      clear!
      block.call
    end
  end

  alias_method :fetch, :get

  def set(key, value)
    @handles[key_for(key)] = value
  end

  def clear!
    each do |key, val|
      next if key.pid == pid

      begin
        val.close
      rescue
        nil
      end
    end
  end

  extend(ForkHandle)
end

Forkhandle = ForkHandle


__END__

ForkHandle.get(:default){ build_default_connection }

ForkHandle.set(:default, build_default_connection)



Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
forkhandle-0.0.1 lib/forkhandle.rb