Module: Spork

Defined in:
lib/spork.rb

Overview

A way to cleanly handle process forking in Sinatra when using Passenger, aka “sporking some code”. This will allow you to properly execute some code asynchronously, which otherwise does not work correctly.

Written by Ron Evans More info at deadprogrammersociety.com

Mostly lifted from the Spawn plugin for Rails (github.com/tra/spawn) but with all of the Rails stuff removed.… cause you are using Sinatra. If you are using Rails, Spawn is what you need. If you are using something else besides Sinatra that is Rack-based under Passenger, and you are having trouble with asynch processing, let me know if spork helped you.

Constant Summary collapse

@@resources =

things to close in child process

[]

Class Method Summary collapse

Class Method Details

.close_resourcesObject

close all the resources added by calls to resource_to_close



25
26
27
28
29
30
# File 'lib/spork.rb', line 25

def self.close_resources
  @@resources.each do |resource|
    resource.close if resource && resource.respond_to?(:close) && !resource.closed?
  end
  @@resources = []
end

.resource_to_close(resource) ⇒ Object

set the resource to disconnect from in the child process (when forking)



20
21
22
# File 'lib/spork.rb', line 20

def self.resource_to_close(resource)
  @@resources << resource
end

.resourcesObject



15
16
17
# File 'lib/spork.rb', line 15

def self.resources
  @@resources
end

.spork(options = {}) ⇒ Object

actually perform the fork… er, spork valid options are: :priority => to set the process priority of the child :logger => a logger object to use from the child :no_detach => true if you want to keep the child process under the parent control. usually you do NOT want this



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/spork.rb', line 37

def self.spork(options={})
  logger = options[:logger]
  logger.debug "spork> parent PID = #{Process.pid}" if logger
  
  child = fork do
    begin
      start = Time.now
      logger.debug "spork> child PID = #{Process.pid}" if logger

      # set the nice priority if needed
      Process.setpriority(Process::PRIO_PROCESS, 0, options[:priority]) if options[:priority]

      # disconnect from the rack
      Spork.close_resources

      # run the block of code that takes so long
      yield

    rescue => ex
      #raise ex
      logger.error "spork> Exception in child[#{Process.pid}] - #{ex.class}: #{ex.message}" if logger
    ensure
      logger.info "spork> child[#{Process.pid}] took #{Time.now - start} sec" if logger
      # this form of exit doesn't call at_exit handlers
      exit!(0)
    end
  end

  # detach from child process (parent may still wait for detached process if they wish)
  Process.detach(child) unless options[:no_detach]

  return child
end