deadly_serious 0.4.1 → 0.5.0
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/.gitignore +9 -7
- data/deadly_serious.gemspec +0 -1
- data/lib/deadly_serious/engine/base_process.rb +11 -0
- data/lib/deadly_serious/engine/channel.rb +36 -3
- data/lib/deadly_serious/engine/lazy_io.rb +55 -0
- data/lib/deadly_serious/engine/open_io.rb +37 -0
- data/lib/deadly_serious/engine/spawner.rb +73 -51
- data/lib/deadly_serious/processes/resilient_splitter.rb +34 -0
- data/lib/deadly_serious/processes/splitter.rb +17 -5
- data/lib/deadly_serious/version.rb +1 -1
- data/scripts/update_ctags.sh +1 -0
- metadata +6 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c9050728b34b8dd157c703876d8e5fe9e60a8453
|
|
4
|
+
data.tar.gz: 613441848d930e6429eac0660040f795ce868f94
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4294cc634cc2b4b417f4f0dff25f7a8a706d5ef1e262505d0dcf14f8a4834cf9ce22e19c906bd04c5bcf27792a5b8045ccf5e0c18a7e68a77d461af35da99064
|
|
7
|
+
data.tar.gz: d7f9fd19630d96c51b79524b6d0c2995023aad7b1ca0d9df49e96e18953ab856e4f43e961bb913cde0b7cc868bcdcae4016f3f654c45816e3605983e26c33b2d
|
data/.gitignore
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
*.gem
|
|
2
|
-
*.rbc
|
|
3
1
|
.bundle
|
|
4
2
|
.config
|
|
5
|
-
.
|
|
6
|
-
Gemfile.lock
|
|
7
|
-
InstalledFiles
|
|
8
|
-
_yardoc
|
|
3
|
+
.idea/
|
|
9
4
|
coverage
|
|
10
5
|
doc/
|
|
6
|
+
*.gem
|
|
7
|
+
Gemfile.lock
|
|
8
|
+
InstalledFiles
|
|
11
9
|
lib/bundler/man
|
|
10
|
+
output.data
|
|
12
11
|
pkg
|
|
12
|
+
*.rbc
|
|
13
13
|
rdoc
|
|
14
14
|
spec/reports
|
|
15
|
+
tags
|
|
15
16
|
test/tmp
|
|
16
17
|
test/version_tmp
|
|
17
18
|
tmp
|
|
18
|
-
|
|
19
|
+
_yardoc
|
|
20
|
+
.yardoc
|
data/deadly_serious.gemspec
CHANGED
|
@@ -8,16 +8,27 @@ module DeadlySerious
|
|
|
8
8
|
reader.each { |packet| super(packet.chomp) }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
# Alias to #send
|
|
12
|
+
def emit(packet = nil)
|
|
13
|
+
send(packet)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Send a packet to the next process
|
|
11
17
|
def send(packet = nil)
|
|
12
18
|
send_buffered(packet)
|
|
13
19
|
flush_buffer
|
|
14
20
|
end
|
|
15
21
|
|
|
22
|
+
# Send a packet to the next process,
|
|
23
|
+
# however, accumulate some of them
|
|
24
|
+
# before send to gain a little
|
|
25
|
+
# efficency.
|
|
16
26
|
def send_buffered(packet = nil)
|
|
17
27
|
@writer << packet if packet
|
|
18
28
|
@writer << "\n"
|
|
19
29
|
end
|
|
20
30
|
|
|
31
|
+
# Send all not yet sent packets.
|
|
21
32
|
def flush_buffer
|
|
22
33
|
@writer.flush
|
|
23
34
|
end
|
|
@@ -1,19 +1,40 @@
|
|
|
1
1
|
require 'socket'
|
|
2
|
+
require 'deadly_serious/engine/lazy_io'
|
|
2
3
|
|
|
3
4
|
module DeadlySerious
|
|
4
5
|
module Engine
|
|
5
6
|
# Fake class, it's actually a factory ¬¬
|
|
6
7
|
module Channel
|
|
7
|
-
def self.new(name
|
|
8
|
+
def self.new(name)
|
|
8
9
|
matcher = name.match(/^(>)?(.*?)(?:(:)(\d{1,5}))?$/)
|
|
9
10
|
if matcher[1] == '>'
|
|
10
|
-
FileChannel.new(matcher[2], data_dir)
|
|
11
|
+
FileChannel.new(matcher[2], @data_dir)
|
|
11
12
|
elsif matcher[3] == ':'
|
|
12
13
|
SocketChannel.new(matcher[2], matcher[4].to_i)
|
|
13
14
|
else
|
|
14
|
-
PipeChannel.new(matcher[2], pipe_dir)
|
|
15
|
+
PipeChannel.new(matcher[2], @pipe_dir)
|
|
15
16
|
end
|
|
16
17
|
end
|
|
18
|
+
|
|
19
|
+
def self.config(data_dir, pipe_dir, preserve_pipe_dir)
|
|
20
|
+
@data_dir = data_dir
|
|
21
|
+
@pipe_dir = pipe_dir
|
|
22
|
+
@preserve_pipe_dir = preserve_pipe_dir
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.setup
|
|
26
|
+
FileUtils.mkdir_p(@pipe_dir) unless File.exist?(@pipe_dir)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.teardown
|
|
30
|
+
if !@preserve_pipe_dir && File.exist?(@pipe_dir)
|
|
31
|
+
FileUtils.rm_r(@pipe_dir, force: true, secure: true)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.create_pipe(pipe_name)
|
|
36
|
+
new(pipe_name).create
|
|
37
|
+
end
|
|
17
38
|
end
|
|
18
39
|
|
|
19
40
|
class FileChannel
|
|
@@ -35,6 +56,10 @@ module DeadlySerious
|
|
|
35
56
|
fail %(File "#{@io_name}" not found) unless File.exist?(@io_name)
|
|
36
57
|
open(@io_name, 'w')
|
|
37
58
|
end
|
|
59
|
+
|
|
60
|
+
def io
|
|
61
|
+
LazyIo.new(self)
|
|
62
|
+
end
|
|
38
63
|
end
|
|
39
64
|
|
|
40
65
|
class PipeChannel
|
|
@@ -56,6 +81,10 @@ module DeadlySerious
|
|
|
56
81
|
fail %(Pipe "#{@io_name}" not found) unless File.exist?(@io_name)
|
|
57
82
|
open(@io_name, 'w')
|
|
58
83
|
end
|
|
84
|
+
|
|
85
|
+
def io
|
|
86
|
+
LazyIo.new(self)
|
|
87
|
+
end
|
|
59
88
|
end
|
|
60
89
|
|
|
61
90
|
class SocketChannel
|
|
@@ -83,6 +112,10 @@ module DeadlySerious
|
|
|
83
112
|
server = TCPServer.new(@port)
|
|
84
113
|
server.accept
|
|
85
114
|
end
|
|
115
|
+
|
|
116
|
+
def io
|
|
117
|
+
LazyIo.new(self)
|
|
118
|
+
end
|
|
86
119
|
end
|
|
87
120
|
end
|
|
88
121
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module DeadlySerious
|
|
2
|
+
module Engine
|
|
3
|
+
|
|
4
|
+
# Restrict IO class that opens ONLY
|
|
5
|
+
# when trying to read something.
|
|
6
|
+
#
|
|
7
|
+
# Also, used to reopend lost connections.
|
|
8
|
+
#
|
|
9
|
+
# By "restrict", I mean it implements
|
|
10
|
+
# just a few IO operations.
|
|
11
|
+
class LazyIo
|
|
12
|
+
def initialize(channel)
|
|
13
|
+
@channel = channel
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def gets
|
|
17
|
+
open_reader
|
|
18
|
+
@io.gets
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def each(&block)
|
|
22
|
+
open_reader
|
|
23
|
+
@io.each &block
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def <<(element)
|
|
27
|
+
open_writer
|
|
28
|
+
@io << element
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def closed?
|
|
32
|
+
@io.nil? || @io.closed?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def close
|
|
36
|
+
@io.close
|
|
37
|
+
@io = nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def open_reader
|
|
43
|
+
if closed?
|
|
44
|
+
@io = @channel.open_reader
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def open_writer
|
|
49
|
+
if closed?
|
|
50
|
+
@io = @channel.open_writer
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module DeadlySerious
|
|
4
|
+
module Engine
|
|
5
|
+
module OpenIo
|
|
6
|
+
def run(*args, readers: [], writers:[])
|
|
7
|
+
opened_readers = readers.map { |reader| wrap_io(reader) }
|
|
8
|
+
opened_writers = writers.map { |writer| wrap_io(writer) }
|
|
9
|
+
super(*args, readers: opened_readers, writers: opened_writers)
|
|
10
|
+
ensure
|
|
11
|
+
if opened_writers
|
|
12
|
+
opened_writers.each { |writer| close_io(writer) }
|
|
13
|
+
end
|
|
14
|
+
if opened_readers
|
|
15
|
+
opened_readers.each { |reader| close_io(reader) }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def close_io(io)
|
|
22
|
+
return unless io
|
|
23
|
+
return if io.closed?
|
|
24
|
+
io.close
|
|
25
|
+
rescue => e
|
|
26
|
+
# Intentionally eat the error
|
|
27
|
+
# because it's being used inside
|
|
28
|
+
# an "ensure" block
|
|
29
|
+
puts e.inspect
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def wrap_io(pipe_name)
|
|
33
|
+
Channel.new(pipe_name).io
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -1,55 +1,75 @@
|
|
|
1
|
-
require 'fileutils'
|
|
2
1
|
require 'deadly_serious/engine/channel'
|
|
2
|
+
require 'deadly_serious/engine/open_io'
|
|
3
|
+
require 'deadly_serious/processes/splitter'
|
|
3
4
|
|
|
4
5
|
module DeadlySerious
|
|
5
6
|
module Engine
|
|
6
7
|
class Spawner
|
|
7
|
-
def initialize(data_dir: './data',
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@preserve_pipe_dir = preserve_pipe_dir
|
|
8
|
+
def initialize(data_dir: './data',
|
|
9
|
+
pipe_dir: "/tmp/deadly_serious/#{Process.pid}",
|
|
10
|
+
preserve_pipe_dir: false)
|
|
11
11
|
@ids = []
|
|
12
|
-
|
|
13
|
-
FileUtils.mkdir_p(pipe_dir) unless File.exist?(pipe_dir)
|
|
12
|
+
Channel.config(data_dir, pipe_dir, preserve_pipe_dir)
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
def run
|
|
16
|
+
Channel.setup
|
|
17
17
|
run_pipeline
|
|
18
18
|
wait_children
|
|
19
|
-
rescue
|
|
19
|
+
rescue => e
|
|
20
20
|
kill_children
|
|
21
21
|
raise e
|
|
22
22
|
ensure
|
|
23
|
-
|
|
24
|
-
FileUtils.rm_r(@pipe_dir, force: true, secure: true)
|
|
25
|
-
end
|
|
23
|
+
Channel.teardown
|
|
26
24
|
end
|
|
27
25
|
|
|
28
|
-
def
|
|
29
|
-
create_pipe(writer)
|
|
26
|
+
def spawn_process(a_class, *args, process_name: a_class.name, readers: [], writers: [])
|
|
27
|
+
writers.each { |writer| create_pipe(writer) }
|
|
30
28
|
fork_it do
|
|
31
|
-
set_process_name(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
end
|
|
29
|
+
set_process_name(process_name)
|
|
30
|
+
append_open_io_if_needed(a_class)
|
|
31
|
+
a_class.new.run(*args, readers: readers, writers: writers)
|
|
35
32
|
end
|
|
36
33
|
end
|
|
37
34
|
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
35
|
+
def spawn_processes(a_class, *args, process_name: a_class.name, reader_pattern: nil, writers: [])
|
|
36
|
+
number = last_number(reader_pattern)
|
|
37
|
+
|
|
38
|
+
loop do
|
|
39
|
+
this_reader = pattern_replace(reader_pattern, number)
|
|
40
|
+
break unless Channel.exists?(this_reader)
|
|
41
|
+
spawn_process(a_class,
|
|
42
|
+
*args,
|
|
43
|
+
process_name: process_name,
|
|
44
|
+
readers: [this_reader],
|
|
45
|
+
writers: Array(writers))
|
|
46
|
+
number += 1
|
|
50
47
|
end
|
|
51
48
|
end
|
|
52
49
|
|
|
50
|
+
def spawn_source(a_class, *args, writer: a_class.dasherize(a_class.name))
|
|
51
|
+
spawn_process(a_class, *args, process_name: process_name, readers: [], writers: [writer])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def spawn_splitter(process_name: 'Splitter', reader: nil, writer: '>output01.txt', number: 2)
|
|
55
|
+
start = last_number(writer)
|
|
56
|
+
finish = start + number - 1
|
|
57
|
+
|
|
58
|
+
writers = (start..finish).map { |index| pattern_replace(writer, index) }
|
|
59
|
+
|
|
60
|
+
spawn_process(Processes::Splitter,
|
|
61
|
+
process_name: process_name,
|
|
62
|
+
readers: Array(reader),
|
|
63
|
+
writers: writers)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def spawn_socket_splitter(process_name: 'SocketSplitter', reader: nil, port: 11000, number: 2)
|
|
67
|
+
spawn_splitter(process_name: process_name,
|
|
68
|
+
reader: reader,
|
|
69
|
+
writer: "localhost:#{port}",
|
|
70
|
+
number: number)
|
|
71
|
+
end
|
|
72
|
+
|
|
53
73
|
def spawn_command(a_shell_command)
|
|
54
74
|
command = a_shell_command.dup
|
|
55
75
|
a_shell_command.scan(/\(\((.*?)\)\)/) do |(pipe_name)|
|
|
@@ -61,12 +81,18 @@ module DeadlySerious
|
|
|
61
81
|
|
|
62
82
|
private
|
|
63
83
|
|
|
84
|
+
def append_open_io_if_needed(a_class)
|
|
85
|
+
a_class.send(:prepend, OpenIo) unless a_class.include?(OpenIo)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def create_pipe(pipe_name)
|
|
89
|
+
Channel.create_pipe(pipe_name)
|
|
90
|
+
end
|
|
91
|
+
|
|
64
92
|
# @!group Process Control
|
|
65
93
|
|
|
66
94
|
def fork_it
|
|
67
|
-
@ids << fork
|
|
68
|
-
yield
|
|
69
|
-
end
|
|
95
|
+
@ids << fork { yield }
|
|
70
96
|
end
|
|
71
97
|
|
|
72
98
|
def wait_children
|
|
@@ -83,34 +109,30 @@ module DeadlySerious
|
|
|
83
109
|
end
|
|
84
110
|
|
|
85
111
|
# @!endgroup
|
|
86
|
-
# @!group
|
|
112
|
+
# @!group Minor Helpers
|
|
87
113
|
|
|
88
|
-
def
|
|
89
|
-
|
|
114
|
+
def self.dasherize(a_string)
|
|
115
|
+
a_string.gsub(/(.)([A-Z])/, '\1-\2').downcase.gsub(/\W+/, '-')
|
|
90
116
|
end
|
|
91
117
|
|
|
92
|
-
def
|
|
93
|
-
|
|
94
|
-
|
|
118
|
+
def last_number_pattern(a_string)
|
|
119
|
+
last_number_pattern = /(\d+)[^\d]*$/.match(a_string)
|
|
120
|
+
raise %(Writer name "#{writer}" should have a number) if last_number_pattern.nil?
|
|
95
121
|
|
|
96
|
-
|
|
97
|
-
channel_for(pipe_name).open_reader
|
|
122
|
+
last_number_pattern[1]
|
|
98
123
|
end
|
|
99
124
|
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
return channel.open_writer unless block_given?
|
|
103
|
-
|
|
104
|
-
channel.open_writer do |io|
|
|
105
|
-
yield io
|
|
106
|
-
end
|
|
125
|
+
def last_number(a_string)
|
|
126
|
+
last_number_pattern(a_string).to_i
|
|
107
127
|
end
|
|
108
128
|
|
|
109
|
-
|
|
110
|
-
|
|
129
|
+
def pattern_replace(a_string, number)
|
|
130
|
+
pattern = last_number_pattern(a_string)
|
|
131
|
+
pattern_length = pattern.size
|
|
132
|
+
find_pattern = /#{pattern}([^\d]*)$/
|
|
133
|
+
replace_pattern = "%0.#{pattern_length}d\\1"
|
|
111
134
|
|
|
112
|
-
|
|
113
|
-
a_string.gsub(/(.)([A-Z])/, '\1-\2').downcase.gsub(/\W+/, '-')
|
|
135
|
+
a_string.sub(find_pattern, sprintf(replace_pattern, number))
|
|
114
136
|
end
|
|
115
137
|
end
|
|
116
138
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module DeadlySerious
|
|
2
|
+
module Processes
|
|
3
|
+
class ResilientSplitter
|
|
4
|
+
def initialize
|
|
5
|
+
@reallocate = false
|
|
6
|
+
Signal.trap('USR1') do
|
|
7
|
+
@reallocate = true
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def run(readers: [], writers: [])
|
|
12
|
+
reader = readers.first
|
|
13
|
+
outputs = writers.dup
|
|
14
|
+
current = nil
|
|
15
|
+
reader.each do |line|
|
|
16
|
+
begin
|
|
17
|
+
if @reallocate
|
|
18
|
+
@reallocate = false
|
|
19
|
+
outputs = writers.dup
|
|
20
|
+
end
|
|
21
|
+
current = outputs.first
|
|
22
|
+
current << line
|
|
23
|
+
outputs.rotate!
|
|
24
|
+
rescue Errno::EPIPE => e
|
|
25
|
+
puts e.inspect
|
|
26
|
+
outputs.delete(current)
|
|
27
|
+
raise e if outputs.empty?
|
|
28
|
+
redo
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
module DeadlySerious
|
|
2
2
|
module Processes
|
|
3
3
|
class Splitter
|
|
4
|
+
def initialize
|
|
5
|
+
Signal.trap('USR1') { @outputs = @writers.dup }
|
|
6
|
+
end
|
|
4
7
|
def run(readers: [], writers: [])
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
@writers ||= writers
|
|
9
|
+
reader = readers.first
|
|
10
|
+
@outputs = @writers.dup
|
|
11
|
+
begin
|
|
12
|
+
reader.each do |line|
|
|
13
|
+
@current = @outputs.first
|
|
14
|
+
@current << line
|
|
15
|
+
@outputs.rotate!
|
|
16
|
+
end
|
|
17
|
+
rescue => e
|
|
18
|
+
puts e.inspect
|
|
19
|
+
@outputs.delete(@current)
|
|
20
|
+
raise e if @outputs.empty?
|
|
21
|
+
retry
|
|
10
22
|
end
|
|
11
23
|
end
|
|
12
24
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ctags -R . --exclude=.git
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: deadly_serious
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ronie Uliana
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-
|
|
11
|
+
date: 2013-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -38,20 +38,6 @@ dependencies:
|
|
|
38
38
|
- - '>='
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: yard
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - '>='
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '0'
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - '>='
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '0'
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
42
|
name: json
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -84,13 +70,17 @@ files:
|
|
|
84
70
|
- lib/deadly_serious/engine/channel.rb
|
|
85
71
|
- lib/deadly_serious/engine/json_io.rb
|
|
86
72
|
- lib/deadly_serious/engine/json_process.rb
|
|
73
|
+
- lib/deadly_serious/engine/lazy_io.rb
|
|
74
|
+
- lib/deadly_serious/engine/open_io.rb
|
|
87
75
|
- lib/deadly_serious/engine/push_pop.rb
|
|
88
76
|
- lib/deadly_serious/engine/push_pop_send.rb
|
|
89
77
|
- lib/deadly_serious/engine/spawner.rb
|
|
90
78
|
- lib/deadly_serious/processes/db_source.rb
|
|
91
79
|
- lib/deadly_serious/processes/joiner.rb
|
|
80
|
+
- lib/deadly_serious/processes/resilient_splitter.rb
|
|
92
81
|
- lib/deadly_serious/processes/splitter.rb
|
|
93
82
|
- lib/deadly_serious/version.rb
|
|
83
|
+
- scripts/update_ctags.sh
|
|
94
84
|
homepage: https://github.com/ruliana/deadly_serious
|
|
95
85
|
licenses:
|
|
96
86
|
- MIT
|
|
@@ -119,4 +109,3 @@ summary: Flow Based Programming engine that relies on named pipes and Linux proc
|
|
|
119
109
|
with the Operating System, i.e., the S.O. is *part* of the program, it's not something
|
|
120
110
|
*below* it.
|
|
121
111
|
test_files: []
|
|
122
|
-
has_rdoc:
|