Skip to content

Commit

Permalink
Support idle_timeout in global compiler (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
ntkme authored Dec 1, 2023
1 parent 4ae0d84 commit a81f9bb
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
2 changes: 1 addition & 1 deletion lib/sass/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module Sass
# sass.close
class Compiler
def initialize
@dispatcher = ResilientDispatcher.new
@dispatcher = ResilientDispatcher.new(Dispatcher)
end

# Compiles the Sass file at +path+ to CSS.
Expand Down
8 changes: 7 additions & 1 deletion lib/sass/compiler/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def unsubscribe(id)
close
end
else
@id = 1
idle
end
end
end
Expand Down Expand Up @@ -90,6 +90,12 @@ def send_proto(...)
@connection.write(...)
end

private

def idle
@id = 1
end

# The {Channel} between {Dispatcher} and {Host}.
class Channel
attr_reader :id
Expand Down
7 changes: 4 additions & 3 deletions lib/sass/compiler/resilient_dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ class Compiler
#
# It recovers from failures and continues to function.
class ResilientDispatcher
def initialize
@dispatcher = Dispatcher.new
def initialize(dispatcher_class)
@dispatcher_class = dispatcher_class
@dispatcher = @dispatcher_class.new
@mutex = Mutex.new
end

Expand All @@ -29,7 +30,7 @@ def connect(...)
@mutex.synchronize do
@dispatcher.connect(...)
rescue Errno::EBUSY
@dispatcher = Dispatcher.new
@dispatcher = @dispatcher_class.new
@dispatcher.connect(...)
end
end
Expand Down
38 changes: 37 additions & 1 deletion lib/sass/embedded.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,43 @@ def compiler
@mutex.synchronize do
return @compiler if @compiler

compiler = Compiler.new
compiler = Class.new(Compiler) do
def initialize
@dispatcher = self.class.const_get(:ResilientDispatcher).new(Class.new(self.class.const_get(:Dispatcher)) do
def initialize
super

idle_timeout = 10
@last_accessed_time = current_time

Thread.new do
duration = idle_timeout
loop do
sleep(duration.negative? ? idle_timeout : duration)
evicted = @mutex.synchronize do
duration = idle_timeout - (current_time - @last_accessed_time)
@id = 0xffffffff if @observers.empty? && duration.negative?
end
break if evicted
end
close
end
end

private

def idle
super

@last_accessed_time = current_time
end

def current_time
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
end)
end
end.new

Process.singleton_class.prepend(Module.new do
define_method :_fork do
Expand Down

0 comments on commit a81f9bb

Please sign in to comment.