deadly_serious 0.8.1 → 0.9.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 +0 -3
- data/deadly_serious.gemspec +3 -4
- data/lib/deadly_serious/engine/auto_pipe.rb +39 -0
- data/lib/deadly_serious/engine/channel.rb +11 -44
- data/lib/deadly_serious/engine/lazy_io.rb +4 -11
- data/lib/deadly_serious/engine/spawner.rb +23 -10
- data/lib/deadly_serious/processes/splitter.rb +1 -1
- data/lib/deadly_serious/version.rb +1 -1
- data/lib/deadly_serious.rb +0 -1
- metadata +19 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b91d01c54129f8158a8f1a949e21b52d938edc11
|
4
|
+
data.tar.gz: a02ba9c6fbc11c1a1310b76877ba8af122591374
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fffa36bdf4a5e981f79de9e6c0e3c55d30ef40a6e71e5951d9b66098d5f18e7b87bc2907db40cd97c23601fc1aefc698d237329c3542a040aaad8df127d70fae
|
7
|
+
data.tar.gz: d28eb902110fea51d82f95a68f5682051e27e251540b6cc3d469058b7b578dca96bf268c55953a5be6572b37a9ffad83c1085546d60df587a10afe7fbd69544c
|
data/.gitignore
CHANGED
data/deadly_serious.gemspec
CHANGED
@@ -18,9 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
22
|
-
spec.add_development_dependency 'rake'
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
23
|
|
24
|
-
spec.add_dependency '
|
25
|
-
spec.add_dependency 'json', '~> 1.8'
|
24
|
+
spec.add_dependency 'json'
|
26
25
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class DeadlySerious::Engine::AutoPipe
|
2
|
+
TEMPLATE = '%s.connection.%04d'
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@net_id = 0
|
6
|
+
@connection_stack = []
|
7
|
+
@counter = Hash.new { |h, k| h[k.to_sym] = 0}
|
8
|
+
end
|
9
|
+
|
10
|
+
def on_subnet
|
11
|
+
@net_id += 1
|
12
|
+
@connection_stack << sprintf('%04d', @net_id)
|
13
|
+
yield
|
14
|
+
ensure
|
15
|
+
@connection_stack.pop
|
16
|
+
end
|
17
|
+
|
18
|
+
def net_id
|
19
|
+
(@connection_stack.last || 'top').to_sym
|
20
|
+
end
|
21
|
+
|
22
|
+
def counter
|
23
|
+
@counter[net_id]
|
24
|
+
end
|
25
|
+
|
26
|
+
def next
|
27
|
+
advance_counter
|
28
|
+
last
|
29
|
+
end
|
30
|
+
|
31
|
+
def last
|
32
|
+
sprintf(TEMPLATE, net_id, counter)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def advance_counter
|
37
|
+
@counter[net_id] += 1
|
38
|
+
end
|
39
|
+
end
|
@@ -4,15 +4,11 @@ require 'deadly_serious/engine/lazy_io'
|
|
4
4
|
module DeadlySerious
|
5
5
|
module Engine
|
6
6
|
# Fake class, it's actually a factory ¬¬
|
7
|
-
# Creates a pipe, file or socket, depending on the name informed:
|
8
|
-
# xyz # create a pipe
|
9
|
-
# >xyz # create a file
|
10
|
-
# xyz:8080 # create a socket
|
11
7
|
module Channel
|
12
8
|
def self.new(name)
|
13
9
|
matcher = name.match(/^(>)?(.*?)(?:(:)(\d{1,5}))?$/)
|
14
10
|
if matcher[1] == '>'
|
15
|
-
FileChannel.new(matcher[2], @data_dir
|
11
|
+
FileChannel.new(matcher[2], @data_dir)
|
16
12
|
elsif matcher[3] == ':'
|
17
13
|
SocketChannel.new(matcher[2], matcher[4].to_i)
|
18
14
|
else
|
@@ -20,26 +16,20 @@ module DeadlySerious
|
|
20
16
|
end
|
21
17
|
end
|
22
18
|
|
23
|
-
def self.config(data_dir, pipe_dir,
|
19
|
+
def self.config(data_dir, pipe_dir, preserve_pipe_dir)
|
24
20
|
@data_dir = data_dir
|
25
21
|
@pipe_dir = pipe_dir
|
26
|
-
@lock_dir = lock_dir
|
27
22
|
@preserve_pipe_dir = preserve_pipe_dir
|
28
|
-
@preserve_lock_dir = preserve_lock_dir
|
29
23
|
end
|
30
24
|
|
31
25
|
def self.setup
|
32
26
|
FileUtils.mkdir_p(@pipe_dir) unless File.exist?(@pipe_dir)
|
33
|
-
FileUtils.mkdir_p(@lock_dir) unless File.exist?(@lock_dir)
|
34
27
|
end
|
35
28
|
|
36
29
|
def self.teardown
|
37
30
|
if !@preserve_pipe_dir && File.exist?(@pipe_dir)
|
38
31
|
FileUtils.rm_r(@pipe_dir, force: true, secure: true)
|
39
32
|
end
|
40
|
-
if !@preserve_lock_dir && File.exist?(@lock_dir)
|
41
|
-
FileUtils.rm_r(@lock_dir, force: true, secure: true)
|
42
|
-
end
|
43
33
|
end
|
44
34
|
|
45
35
|
def self.create_pipe(pipe_name)
|
@@ -48,40 +38,19 @@ module DeadlySerious
|
|
48
38
|
end
|
49
39
|
|
50
40
|
class FileChannel
|
51
|
-
|
41
|
+
attr_reader :io_name
|
42
|
+
|
43
|
+
def initialize(name, directory)
|
52
44
|
@io_name = File.join(directory, name)
|
53
|
-
@readlock_file = "#{temp_dir}/#{name}.readlock"
|
54
45
|
end
|
55
46
|
|
56
47
|
def create
|
57
|
-
unless File.exist?(@io_name)
|
58
|
-
`touch #{@io_name} && touch #{@readlock_file}`
|
59
|
-
end
|
48
|
+
`touch #{@io_name}` unless File.exist?(@io_name)
|
60
49
|
@io_name
|
61
50
|
end
|
62
51
|
|
63
|
-
def on_close
|
64
|
-
FileUtils.rm_f(@readlock_file)
|
65
|
-
end
|
66
|
-
|
67
|
-
# If the file has a "readlock", blocks the opening
|
68
|
-
# until the readlock be removed.
|
69
52
|
def open_reader
|
70
53
|
fail %(File "#{@io_name}" not found) unless File.exist?(@io_name)
|
71
|
-
return open(@io_name, 'r') unless File.exist?(@readlock_file)
|
72
|
-
|
73
|
-
notifier = INotify::Notifier.new
|
74
|
-
file = nil
|
75
|
-
notifier.watch(@readlock_file, :delete) do
|
76
|
-
file = open(@io_name, 'r')
|
77
|
-
end
|
78
|
-
notifier.process
|
79
|
-
file
|
80
|
-
|
81
|
-
rescue Errno::ENOENT
|
82
|
-
# Should occur ONLY if we deleted the
|
83
|
-
# readlock file after the guard clause
|
84
|
-
# and before the Notifier initialization.
|
85
54
|
open(@io_name, 'r')
|
86
55
|
end
|
87
56
|
|
@@ -96,6 +65,8 @@ module DeadlySerious
|
|
96
65
|
end
|
97
66
|
|
98
67
|
class PipeChannel
|
68
|
+
attr_reader :io_name
|
69
|
+
|
99
70
|
def initialize(name, directory)
|
100
71
|
@io_name = File.join(directory, name)
|
101
72
|
end
|
@@ -105,10 +76,6 @@ module DeadlySerious
|
|
105
76
|
@io_name
|
106
77
|
end
|
107
78
|
|
108
|
-
def on_close
|
109
|
-
# Do nothing
|
110
|
-
end
|
111
|
-
|
112
79
|
def open_reader
|
113
80
|
fail %(Pipe "#{@io_name}" not found) unless File.exist?(@io_name)
|
114
81
|
open(@io_name, 'r')
|
@@ -130,11 +97,11 @@ module DeadlySerious
|
|
130
97
|
@retry_counter = 3
|
131
98
|
end
|
132
99
|
|
133
|
-
def
|
134
|
-
#
|
100
|
+
def io_name
|
101
|
+
"#{@host}@#{@port}"
|
135
102
|
end
|
136
103
|
|
137
|
-
def
|
104
|
+
def create
|
138
105
|
# Do nothing
|
139
106
|
end
|
140
107
|
|
@@ -2,18 +2,12 @@ module DeadlySerious
|
|
2
2
|
module Engine
|
3
3
|
|
4
4
|
# Restrict IO class that opens ONLY
|
5
|
-
# when trying to read
|
6
|
-
# This way, the channel is opened during
|
7
|
-
# the shortest time possible.
|
5
|
+
# when trying to read something.
|
8
6
|
#
|
9
|
-
#
|
10
|
-
# when they are closed.
|
7
|
+
# Also, used to reopend lost connections.
|
11
8
|
#
|
12
|
-
# By "restrict
|
9
|
+
# By "restrict", I mean it implements
|
13
10
|
# just a few IO operations.
|
14
|
-
#
|
15
|
-
# Note: Maybe it can be completely removed.
|
16
|
-
# for the sake of simplicity
|
17
11
|
class LazyIo
|
18
12
|
def initialize(channel)
|
19
13
|
@channel = channel
|
@@ -54,8 +48,7 @@ module DeadlySerious
|
|
54
48
|
end
|
55
49
|
|
56
50
|
def close
|
57
|
-
@io.close
|
58
|
-
@channel.on_close
|
51
|
+
@io.close unless closed?
|
59
52
|
@io = nil
|
60
53
|
end
|
61
54
|
|
@@ -1,17 +1,29 @@
|
|
1
1
|
require 'deadly_serious/engine/channel'
|
2
2
|
require 'deadly_serious/engine/open_io'
|
3
|
+
require 'deadly_serious/engine/auto_pipe'
|
3
4
|
require 'deadly_serious/processes/splitter'
|
4
5
|
|
5
6
|
module DeadlySerious
|
6
7
|
module Engine
|
7
8
|
class Spawner
|
8
9
|
def initialize(data_dir: './data',
|
9
|
-
pipe_dir: "/tmp/deadly_serious/#{Process.pid}
|
10
|
-
|
11
|
-
preserve_pipe_dir: false,
|
12
|
-
preserve_lock_dir: false)
|
10
|
+
pipe_dir: "/tmp/deadly_serious/#{Process.pid}",
|
11
|
+
preserve_pipe_dir: false)
|
13
12
|
@ids = []
|
14
|
-
|
13
|
+
@auto_pipe = AutoPipe.new
|
14
|
+
Channel.config(data_dir, pipe_dir, preserve_pipe_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_subnet(&block)
|
18
|
+
@auto_pipe.on_subnet &block
|
19
|
+
end
|
20
|
+
|
21
|
+
def next_pipe
|
22
|
+
@auto_pipe.next
|
23
|
+
end
|
24
|
+
|
25
|
+
def last_pipe
|
26
|
+
@auto_pipe.last
|
15
27
|
end
|
16
28
|
|
17
29
|
def run
|
@@ -33,13 +45,14 @@ module DeadlySerious
|
|
33
45
|
writers.each { |writer| create_pipe(writer) }
|
34
46
|
fork_it do
|
35
47
|
begin
|
36
|
-
set_process_name(process_name)
|
48
|
+
set_process_name(process_name, readers, writers)
|
37
49
|
append_open_io_if_needed(a_class)
|
38
50
|
the_object = a_class.new
|
39
51
|
the_object.run(*args, readers: readers, writers: writers)
|
40
|
-
rescue
|
52
|
+
rescue Errno::EPIPE # Broken Pipe, no problem
|
53
|
+
# Ignore
|
54
|
+
ensure
|
41
55
|
the_object.finalize if the_object.respond_to?(:finalize)
|
42
|
-
raise e
|
43
56
|
end
|
44
57
|
end
|
45
58
|
end
|
@@ -117,8 +130,8 @@ module DeadlySerious
|
|
117
130
|
wait_children
|
118
131
|
end
|
119
132
|
|
120
|
-
def set_process_name(name)
|
121
|
-
$0 = "ruby #{self.class.dasherize(name)}"
|
133
|
+
def set_process_name(name, readers, writers)
|
134
|
+
$0 = "ruby #{self.class.dasherize(name)} <(#{readers.join(' ')}) >(#{writers.join(' ')})"
|
122
135
|
end
|
123
136
|
|
124
137
|
# @!endgroup
|
data/lib/deadly_serious.rb
CHANGED
metadata
CHANGED
@@ -1,77 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deadly_serious
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.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: 2014-02-
|
11
|
+
date: 2014-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 1.5.1
|
19
|
+
version: '1.3'
|
23
20
|
type: :development
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.5'
|
30
|
-
- - ">="
|
24
|
+
- - ~>
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version: 1.
|
26
|
+
version: '1.3'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: rake
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
|
-
- -
|
31
|
+
- - '>='
|
38
32
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
33
|
+
version: '0'
|
40
34
|
type: :development
|
41
35
|
prerelease: false
|
42
36
|
version_requirements: !ruby/object:Gem::Requirement
|
43
37
|
requirements:
|
44
|
-
- -
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '10.0'
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: rb-inotify
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0.9'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - "~>"
|
38
|
+
- - '>='
|
59
39
|
- !ruby/object:Gem::Version
|
60
|
-
version: '0
|
40
|
+
version: '0'
|
61
41
|
- !ruby/object:Gem::Dependency
|
62
42
|
name: json
|
63
43
|
requirement: !ruby/object:Gem::Requirement
|
64
44
|
requirements:
|
65
|
-
- -
|
45
|
+
- - '>='
|
66
46
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
47
|
+
version: '0'
|
68
48
|
type: :runtime
|
69
49
|
prerelease: false
|
70
50
|
version_requirements: !ruby/object:Gem::Requirement
|
71
51
|
requirements:
|
72
|
-
- -
|
52
|
+
- - '>='
|
73
53
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
54
|
+
version: '0'
|
75
55
|
description: Flow Based Programming Engine mechanically sympathetic to *nix.
|
76
56
|
email:
|
77
57
|
- ronie.uliana@gmail.com
|
@@ -79,13 +59,14 @@ executables: []
|
|
79
59
|
extensions: []
|
80
60
|
extra_rdoc_files: []
|
81
61
|
files:
|
82
|
-
-
|
62
|
+
- .gitignore
|
83
63
|
- Gemfile
|
84
64
|
- LICENSE.txt
|
85
65
|
- README.md
|
86
66
|
- Rakefile
|
87
67
|
- deadly_serious.gemspec
|
88
68
|
- lib/deadly_serious.rb
|
69
|
+
- lib/deadly_serious/engine/auto_pipe.rb
|
89
70
|
- lib/deadly_serious/engine/base_process.rb
|
90
71
|
- lib/deadly_serious/engine/channel.rb
|
91
72
|
- lib/deadly_serious/engine/json_io.rb
|
@@ -112,17 +93,17 @@ require_paths:
|
|
112
93
|
- lib
|
113
94
|
required_ruby_version: !ruby/object:Gem::Requirement
|
114
95
|
requirements:
|
115
|
-
- -
|
96
|
+
- - '>='
|
116
97
|
- !ruby/object:Gem::Version
|
117
98
|
version: '0'
|
118
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
100
|
requirements:
|
120
|
-
- -
|
101
|
+
- - '>='
|
121
102
|
- !ruby/object:Gem::Version
|
122
103
|
version: '0'
|
123
104
|
requirements: []
|
124
105
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.
|
106
|
+
rubygems_version: 2.1.11
|
126
107
|
signing_key:
|
127
108
|
specification_version: 4
|
128
109
|
summary: Flow Based Programming engine that relies on named pipes and Linux processes
|