io_daemonizer 4 → 7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/io_daemonizer.rb +70 -8
- metadata +4 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 659f573346f478e82593492d57366baa4f704cdad86495f71f9e14d3ab656e53
         | 
| 4 | 
            +
              data.tar.gz: '028c6285884760b1a2fa0330844128c1f63a713bc6efa1b2e6775f4ae3dcd64d'
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ebb22484722226e4761a4a29176f9b62f95513f693653c93adc7deb815f491b5b5711579c8ba29cf2810bb9c16f3e8539201cc287607ac4cf4e73074b35e21fc
         | 
| 7 | 
            +
              data.tar.gz: 3ee8bd1928ca173f3ccd5d9e10e47809bac6224f8e5d2eacece6aaf45d97328d5fcceae3201e3f7dbbe2d8df9059d5cf93dbd2401d117ae2223e224969a53d03
         | 
    
        data/io_daemonizer.rb
    CHANGED
    
    | @@ -1,11 +1,12 @@ | |
| 1 | 
            -
            # io_daemonizer v. | 
| 1 | 
            +
            # io_daemonizer v.7.1 https://github.com/joeyschoblaska/io_daemonizer
         | 
| 2 2 |  | 
| 3 | 
            +
            require "json"
         | 
| 3 4 | 
             
            require "shellwords"
         | 
| 4 5 | 
             
            require "socket"
         | 
| 5 6 | 
             
            require "stringio"
         | 
| 6 7 |  | 
| 7 8 | 
             
            class IODaemonizer
         | 
| 8 | 
            -
              def self.wrap(port:, setup:, run:)
         | 
| 9 | 
            +
              def self.wrap(port:, setup:, run:, autostart: true)
         | 
| 9 10 | 
             
                case ARGV[0]
         | 
| 10 11 | 
             
                when "start"
         | 
| 11 12 | 
             
                  puts "starting server..."
         | 
| @@ -14,18 +15,28 @@ class IODaemonizer | |
| 14 15 | 
             
                  puts "stopping server..."
         | 
| 15 16 | 
             
                  send_request(port: port, args: ARGV)
         | 
| 16 17 | 
             
                else
         | 
| 17 | 
            -
                   | 
| 18 | 
            +
                  begin
         | 
| 19 | 
            +
                    send_request(port: port, args: ARGV)
         | 
| 20 | 
            +
                  rescue Errno::ECONNREFUSED => e
         | 
| 21 | 
            +
                    raise(e) unless autostart
         | 
| 22 | 
            +
                    Daemon.run(port: port, setup: setup, run: run, fork: true)
         | 
| 23 | 
            +
                    sleep 0.1
         | 
| 24 | 
            +
                    send_request(port: port, args: ARGV)
         | 
| 25 | 
            +
                  end
         | 
| 18 26 | 
             
                end
         | 
| 19 27 | 
             
              rescue Errno::ECONNREFUSED
         | 
| 20 28 | 
             
                puts "server not running or not responding"
         | 
| 21 29 | 
             
              end
         | 
| 22 30 |  | 
| 23 31 | 
             
              def self.send_request(port:, args:)
         | 
| 32 | 
            +
                consumer = LabeledIOConsumer.new
         | 
| 33 | 
            +
             | 
| 24 34 | 
             
                TCPSocket.open("127.0.0.1", port) do |socket|
         | 
| 25 35 | 
             
                  socket.puts args.shelljoin
         | 
| 26 36 | 
             
                  socket.write $stdin.tty? ? "" : $stdin.read
         | 
| 27 37 | 
             
                  socket.close_write
         | 
| 28 | 
            -
             | 
| 38 | 
            +
             | 
| 39 | 
            +
                  consumer.write(socket.read) until socket.eof?
         | 
| 29 40 | 
             
                end
         | 
| 30 41 | 
             
              end
         | 
| 31 42 |  | 
| @@ -39,10 +50,10 @@ class IODaemonizer | |
| 39 50 | 
             
              end
         | 
| 40 51 |  | 
| 41 52 | 
             
              class Daemon
         | 
| 42 | 
            -
                def self.run(port:, setup:, run:)
         | 
| 53 | 
            +
                def self.run(port:, setup:, run:, fork: false)
         | 
| 43 54 | 
             
                  daemon = new(port: port, setup: setup, run: run)
         | 
| 44 55 | 
             
                  daemon.setup
         | 
| 45 | 
            -
                  daemon.start
         | 
| 56 | 
            +
                  fork ? Kernel.fork { daemon.start } : daemon.start
         | 
| 46 57 | 
             
                end
         | 
| 47 58 |  | 
| 48 59 | 
             
                def initialize(port:, setup:, run:)
         | 
| @@ -73,14 +84,65 @@ class IODaemonizer | |
| 73 84 | 
             
                  else
         | 
| 74 85 | 
             
                    IODaemonizer.redirect(
         | 
| 75 86 | 
             
                      stdin: StringIO.new(body.join),
         | 
| 76 | 
            -
                      stdout: socket,
         | 
| 77 | 
            -
                      stderr: socket
         | 
| 87 | 
            +
                      stdout: IOLabeler.new(1, socket, "stdout"),
         | 
| 88 | 
            +
                      stderr: IOLabeler.new(2, socket, "stderr")
         | 
| 78 89 | 
             
                    ) { @context.instance_exec args, &@run }
         | 
| 79 90 | 
             
                  end
         | 
| 80 91 | 
             
                rescue => e
         | 
| 81 92 | 
             
                  socket.write e.inspect
         | 
| 93 | 
            +
                  raise e
         | 
| 82 94 | 
             
                ensure
         | 
| 95 | 
            +
                  socket.close_write
         | 
| 83 96 | 
             
                  socket.close
         | 
| 84 97 | 
             
                end
         | 
| 85 98 | 
             
              end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              class IOLabeler < IO
         | 
| 101 | 
            +
                attr_reader :label
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                def initialize(fd, socket, label)
         | 
| 104 | 
            +
                  super(fd)
         | 
| 105 | 
            +
                  @socket = socket
         | 
| 106 | 
            +
                  @label = label
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                def write(chunk)
         | 
| 110 | 
            +
                  @socket.write({ @label => chunk }.to_json)
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                def reopen(io)
         | 
| 114 | 
            +
                  @label = io&.label || @label
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
              end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
              class LabeledIOConsumer
         | 
| 119 | 
            +
                def initialize
         | 
| 120 | 
            +
                  @buffer = ""
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                def write(chunk)
         | 
| 124 | 
            +
                  chunk.chars.each do |ch|
         | 
| 125 | 
            +
                    @buffer << ch
         | 
| 126 | 
            +
                    process_buffer if ch == "}"
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                private
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                def process_buffer
         | 
| 133 | 
            +
                  parsed = JSON.parse(@buffer)
         | 
| 134 | 
            +
                  key = parsed.keys[0]
         | 
| 135 | 
            +
                  value = parsed.values[0]
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                  case key
         | 
| 138 | 
            +
                  when "stdout"
         | 
| 139 | 
            +
                    $stdout.write(value)
         | 
| 140 | 
            +
                  when "stderr"
         | 
| 141 | 
            +
                    $stderr.write(value)
         | 
| 142 | 
            +
                  end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                  @buffer = ""
         | 
| 145 | 
            +
                rescue JSON::ParserError
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
              end
         | 
| 86 148 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,17 +1,17 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: io_daemonizer
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: ' | 
| 4 | 
            +
              version: '7.1'
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Joey Schoblaska
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022-09- | 
| 11 | 
            +
            date: 2022-09-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 | 
            -
            description: Wrap a Ruby script that speaks  | 
| 14 | 
            -
              startup overhead once.
         | 
| 13 | 
            +
            description: Wrap a Ruby script that speaks stdio in a daemon so that you only pay
         | 
| 14 | 
            +
              the startup overhead once.
         | 
| 15 15 | 
             
            email: joey.schoblaska@gmail.com
         | 
| 16 16 | 
             
            executables: []
         | 
| 17 17 | 
             
            extensions: []
         |