lib/sass/embedded/dispatcher.rb
# frozen_string_literal: true module Sass class Embedded # The {Dispatcher} class. # # It dispatches messages between mutliple instances of {Host} and a single {Compiler}. class Dispatcher PROTOCOL_ERROR_ID = 4_294_967_295 def initialize @compiler = Compiler.new @observers = {} @id = 0 @mutex = Mutex.new Thread.new do loop do receive_message EmbeddedProtocol::OutboundMessage.decode @compiler.read rescue IOError => e half_close @observers.each_value do |observer| observer.error e end break end end end def subscribe(observer) @mutex.synchronize do raise EOFError if half_closed? id = @id @id = id.next @observers[id] = observer id end end def unsubscribe(id) @observers.delete(id) close if half_closed? && @observers.empty? end def close @compiler.close end def closed? @compiler.closed? end def send_message(inbound_message) @compiler.write(inbound_message.to_proto) end private def half_close @mutex.synchronize do @id = PROTOCOL_ERROR_ID end end def half_closed? @id == PROTOCOL_ERROR_ID end def receive_message(outbound_message) oneof = outbound_message.message message = outbound_message.public_send(oneof) case oneof when :error half_close @observers[message.id]&.public_send(oneof, message) when :compile_response, :version_response @observers[message.id].public_send(oneof, message) when :log_event, :canonicalize_request, :import_request, :file_import_request, :function_call_request Thread.new(@observers[message.compilation_id]) do |observer| observer.public_send(oneof, message) end else raise ArgumentError, "Unknown OutboundMessage.message #{message}" end end end private_constant :Dispatcher end end