io_daemonizer 5 → 6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/io_daemonizer.rb +59 -4
  3. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80b48adc5074a3057dd995bd6111fffcaecaf14436d94aa781c822eef10fd95b
4
- data.tar.gz: 1f816e2e331f8132844a4fcc1a8da7731d4d08d70165f89ac34c3f985a969466
3
+ metadata.gz: 9221b86c37a20ab3d79c7fb1fee60e9a7c74aa083d3aff30da43e755c9a02256
4
+ data.tar.gz: f0b41de14e06824a163ded73f2b70d45bc54c1c086ee8c2419b83af4d1ab3c58
5
5
  SHA512:
6
- metadata.gz: f531743fc395f854ed431ee7e2f283a206995df75367fe5fe871d8d7d1e238a482b0baf0ea132c8b384055377169870122e443c2840f51b2da092d25c2472dd2
7
- data.tar.gz: fe64289f1d5b86e12f52c157e46cb1d8e5d93ac9f95be18aa46e51f34a81f4a42f77a7ca0d193dc22fca2b0636f4f10349e342a97e6f3c0dd36d783ac1f2ee7b
6
+ metadata.gz: cbcfd15d8a147dc074f4003e7d1a6f2ee17979644220abb54044b740c7023f0f51bab528c395b38b053efb685abac807c4648387b9aa5c1e3cad0d0e45f0ef5f
7
+ data.tar.gz: 250baadd6ca2b943920408f431a66b5920f1655cfd44b4026f7c08409b23dcf9ad19972e2aae7f900e09268d4f9c472c33e80455a62ddf982e78751da9433f44
data/io_daemonizer.rb CHANGED
@@ -1,5 +1,6 @@
1
- # io_daemonizer v.5 https://github.com/joeyschoblaska/io_daemonizer
1
+ # io_daemonizer v.6 https://github.com/joeyschoblaska/io_daemonizer
2
2
 
3
+ require "json"
3
4
  require "shellwords"
4
5
  require "socket"
5
6
  require "stringio"
@@ -30,11 +31,14 @@ class IODaemonizer
30
31
  end
31
32
 
32
33
  def self.send_request(port:, args:)
34
+ consumer = LabeledIOConsumer.new
35
+
33
36
  TCPSocket.open("127.0.0.1", port) do |socket|
34
37
  socket.puts args.shelljoin
35
38
  socket.write $stdin.tty? ? "" : $stdin.read
36
39
  socket.close_write
37
- STDOUT.write(socket.read(4096)) until socket.eof?
40
+
41
+ consumer.write(socket.read) until socket.eof?
38
42
  end
39
43
  end
40
44
 
@@ -82,14 +86,65 @@ class IODaemonizer
82
86
  else
83
87
  IODaemonizer.redirect(
84
88
  stdin: StringIO.new(body.join),
85
- stdout: socket,
86
- stderr: socket
89
+ stdout: IOLabeler.new(1, socket, "stdout"),
90
+ stderr: IOLabeler.new(2, socket, "stderr")
87
91
  ) { @context.instance_exec args, &@run }
88
92
  end
89
93
  rescue => e
90
94
  socket.write e.inspect
95
+ raise e
91
96
  ensure
97
+ socket.close_write
92
98
  socket.close
93
99
  end
94
100
  end
101
+
102
+ class IOLabeler < IO
103
+ attr_reader :label
104
+
105
+ def initialize(fd, socket, label)
106
+ super(fd)
107
+ @socket = socket
108
+ @label = label
109
+ end
110
+
111
+ def write(chunk)
112
+ @socket.write({ @label => chunk }.to_json)
113
+ end
114
+
115
+ def reopen(io)
116
+ @label = io&.label || @label
117
+ end
118
+ end
119
+
120
+ class LabeledIOConsumer
121
+ def initialize
122
+ @buffer = ""
123
+ end
124
+
125
+ def write(chunk)
126
+ chunk.chars.each do |ch|
127
+ @buffer << ch
128
+ process_buffer
129
+ end
130
+ end
131
+
132
+ private
133
+
134
+ def process_buffer
135
+ parsed = JSON.parse(@buffer)
136
+ key = parsed.keys[0]
137
+ value = parsed.values[0]
138
+
139
+ case key
140
+ when "stdout"
141
+ $stdout.write(value)
142
+ when "stderr"
143
+ $stderr.write(value)
144
+ end
145
+
146
+ @buffer = ""
147
+ rescue JSON::ParserError
148
+ end
149
+ end
95
150
  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: '5'
4
+ version: '6'
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-06 00:00:00.000000000 Z
11
+ date: 2022-09-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Wrap a Ruby script that speaks IO in a daemon so that you only pay the
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: []