diff --git a/lib/async/container/notify.rb b/lib/async/container/notify.rb index 3079bab..5dfb155 100644 --- a/lib/async/container/notify.rb +++ b/lib/async/container/notify.rb @@ -6,6 +6,7 @@ require_relative "notify/pipe" require_relative "notify/socket" require_relative "notify/console" +require_relative "notify/log" module Async module Container @@ -18,6 +19,7 @@ def self.open! @client ||= ( Pipe.open! || Socket.open! || + Log.open! || Console.open! ) end diff --git a/lib/async/container/notify/log.rb b/lib/async/container/notify/log.rb new file mode 100644 index 0000000..4992c88 --- /dev/null +++ b/lib/async/container/notify/log.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +# Released under the MIT License. +# Copyright, 2020-2024, by Samuel Williams. + +require_relative "client" +require "socket" + +module Async + module Container + module Notify + class Log < Client + # The name of the environment variable which contains the path to the notification socket. + NOTIFY_LOG = "NOTIFY_LOG" + + # Open a notification client attached to the current {NOTIFY_LOG} if possible. + def self.open!(environment = ENV) + if path = environment.delete(NOTIFY_LOG) + self.new(path) + end + end + + # Initialize the notification client. + # @parameter path [String] The path to the UNIX socket used for sending messages to the process manager. + def initialize(path) + @path = path + end + + # @attribute [String] The path to the UNIX socket used for sending messages to the controller. + attr :path + + # Send the given message. + # @parameter message [Hash] + def send(**message) + data = JSON.dump(message) + + File.open(@path, "a") do |file| + file.puts(data) + end + end + + # Send the specified error. + # `sd_notify` requires an `errno` key, which defaults to `-1` to indicate a generic error. + def error!(text, **message) + message[:errno] ||= -1 + + super + end + end + end + end +end diff --git a/lib/async/container/notify/server.rb b/lib/async/container/notify/server.rb index b75e8be..ca1e25d 100644 --- a/lib/async/container/notify/server.rb +++ b/lib/async/container/notify/server.rb @@ -5,6 +5,7 @@ # Copyright, 2020, by Olle Jonsson. require "tmpdir" +require "socket" require "securerandom" module Async diff --git a/test/async/container/notify/log.rb b/test/async/container/notify/log.rb new file mode 100644 index 0000000..9f02df4 --- /dev/null +++ b/test/async/container/notify/log.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# Released under the MIT License. +# Copyright, 2020-2025, by Samuel Williams. +# Copyright, 2020, by Olle Jonsson. + +require "async/container/controller" +require "async/container/controllers" + +require "tmpdir" + +describe Async::Container::Notify::Pipe do + let(:notify_script) {Async::Container::Controllers.path_for("notify")} + let(:notify_log) {File.expand_path("notify-#{::Process.pid}-#{SecureRandom.hex(8)}.log", Dir.tmpdir)} + + it "receives notification of child status" do + system({"NOTIFY_LOG" => notify_log}, "bundle", "exec", notify_script) + + lines = File.readlines(notify_log).map{|line| JSON.parse(line)} + + expect(lines.last).to be == {"ready" => true} + end +end