Class: Sprockets::Rails::StaticCompiler

Inherits:
Object
  • Object
show all
Defined in:
lib/sprockets/rails/static_compiler_extensions.rb

Constant Summary collapse

KILL_MESSAGE =
"die die die!!!!"

Instance Method Summary collapse

Instance Method Details

#compile_with_workersObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
70
71
72
73
74
75
76
# File 'lib/sprockets/rails/static_compiler_extensions.rb', line 8

def compile_with_workers
  unless ::Rails.application.config.assets.parallel_precompile
    return compile_without_workers
  end

  worker_count = (::Rails.application.config.assets.precompile_workers || 4).to_i

  paths = env.each_logical_path.reject {|logical_path| !compile_path?(logical_path)}
  total_count = paths.length
  manifest = {}

  begin
    workers = 1.upto(worker_count).map do
      fork do
        child_context = ZMQ::Context.new(1)
        child_receiver = child_context.socket(ZMQ::PULL)
        child_sender = child_context.socket(ZMQ::PUSH)
        child_receiver.connect("tcp://127.0.0.1:55546")
        child_sender.connect("tcp://127.0.0.1:55547")

        # Send synchronization string
        child_sender.send_string(Process.pid.to_s)

        loop do
          # Allocate, 0mq requires it. (lol)
          begin
            child_receiver.recv_string(logical_path = "")
          rescue Interrupt
            exit
          end
          if logical_path == KILL_MESSAGE
            exit
          elsif asset = env.find_asset(logical_path)
            child_sender.send_string(Marshal.dump(Hash[logical_path, write_asset(asset)]))
          end
        end
      end
    end

    context = ZMQ::Context.new(1)
    sender = context.socket(ZMQ::PUSH)
    receiver = context.socket(ZMQ::PULL)
    sender.bind("tcp://127.0.0.1:55546")
    receiver.bind("tcp://127.0.0.1:55547")

    # Sync workers by blocking on a recieve from each one
    worker_count.times do
      pid = ''
      receiver.recv_string(pid)
    end

    paths.each do |path|
      sender.send_string(path)
    end

    total_count.times do |x|
      receiver.recv_string(string = "")
      result = Marshal.load(string)
      manifest.update result
    end

  ensure
    if workers
      workers.each {|pid| sender.send_string(KILL_MESSAGE) }
    end
  end

  manifest
end