tresse 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +46 -15
- data/lib/tresse.rb +114 -85
- data/tresse.gemspec +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07e2b40e7224b8da9af9768fb077d0a9552b04ba
|
4
|
+
data.tar.gz: d5e471d9d944580185fe2aa97e53fec105f87ae8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e69445a655dc2d80002b087ff8355d1e344a052919be4944b52c94bef65f4065b3d8eb0cf090a0f0e8276cebc028f002399a8b638d892584b51eaefa2cc881fa
|
7
|
+
data.tar.gz: e812e89f78b44ad82726bc978bd36c780957c645b4fc55278279b770f87ed219c5995ea4ed02a16d5196c78b6d0ebeb87e43ba313d847d0789cff2bb2ff63c2b
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,41 +1,72 @@
|
|
1
1
|
|
2
2
|
# tresse
|
3
3
|
|
4
|
-
A poorly thought out and stupid
|
4
|
+
A poorly thought out and stupid source+map+reduce contraption.
|
5
5
|
|
6
|
+
You source one or more pieces of data, map them a couple of times then reduce them.
|
7
|
+
|
8
|
+
By default, the whole of Tresse uses 8 work threads, it can be changed:
|
9
|
+
```ruby
|
10
|
+
Tresse.max_work_thread_count # => 8
|
11
|
+
|
12
|
+
Tresse.max_work_thread_count = 10
|
13
|
+
|
14
|
+
Tresse.max_work_thread_count # => 10
|
15
|
+
```
|
6
16
|
|
7
17
|
## use
|
8
18
|
|
19
|
+
Two sources flattened together
|
20
|
+
```ruby
|
21
|
+
r =
|
22
|
+
Tresse::Group.new('test0')
|
23
|
+
.source { (0..3).to_a }
|
24
|
+
.source { (4..9).to_a }
|
25
|
+
.values # or .flatten
|
26
|
+
.sort
|
27
|
+
|
28
|
+
r #=> (0..9).to_a
|
9
29
|
```
|
10
|
-
require 'tresse'
|
11
30
|
|
31
|
+
Combining two sources again
|
32
|
+
```ruby
|
12
33
|
r =
|
13
34
|
Tresse::Group.new('test0')
|
14
|
-
.
|
15
|
-
.
|
16
|
-
.collect { |e| e * 2 }
|
35
|
+
.source { (0..3).to_a }
|
36
|
+
.source { ('a'..'c').to_a }
|
37
|
+
.map { |e| e.collect { |e| e * 2 } }
|
38
|
+
.values # or .flatten
|
17
39
|
|
18
40
|
r
|
19
|
-
# =>
|
20
|
-
#
|
21
|
-
# =>
|
41
|
+
# => [ 0, 2, 4, 6, 'aa', 'bb', 'cc' ]
|
42
|
+
# or
|
43
|
+
# => [ 'aa', 'bb', 'cc', 0, 2, 4, 6 ]
|
22
44
|
```
|
23
45
|
|
46
|
+
Each can be used, the outcome of its block is discarded
|
24
47
|
```ruby
|
25
|
-
|
48
|
+
t = []
|
49
|
+
# collecting on the side
|
26
50
|
|
27
51
|
r =
|
28
52
|
Tresse::Group.new('test0')
|
29
|
-
.
|
30
|
-
.
|
31
|
-
.
|
32
|
-
.
|
33
|
-
.inject([]) { |a, e| a << e.first; a.sort }
|
53
|
+
.source { (0..3).to_a }
|
54
|
+
.source { ('a'..'c').to_a }
|
55
|
+
.each { |e| t << e.collect { |e| e * 2 } }
|
56
|
+
.values
|
34
57
|
|
35
58
|
r
|
36
|
-
# =>
|
59
|
+
# => [ 0, 1, 2, 3, 'a', 'b', 'c' ]
|
60
|
+
# or
|
61
|
+
# => [ 'a', 'b', 'c', 0, 1, 2, 3 ]
|
62
|
+
|
63
|
+
t
|
64
|
+
# => [ [ 0, 2, 4, 6 ], [ 'aa', 'bb', 'cc' ] ]
|
65
|
+
# or
|
66
|
+
# => [ [ 'aa', 'bb', 'cc' ], [ 0, 2, 4, 6 ] ]
|
37
67
|
```
|
38
68
|
|
69
|
+
|
39
70
|
## license
|
40
71
|
|
41
72
|
MIT, see [LICENSE.txt](LICENSE.txt)
|
data/lib/tresse.rb
CHANGED
@@ -4,27 +4,23 @@ require 'thread'
|
|
4
4
|
|
5
5
|
module Tresse
|
6
6
|
|
7
|
-
VERSION = '
|
7
|
+
VERSION = '1.0.0'
|
8
8
|
|
9
9
|
class << self
|
10
10
|
|
11
|
-
attr_accessor :max_work_threads
|
12
|
-
|
13
11
|
def init
|
14
12
|
|
15
|
-
@max_work_threads = 7
|
16
13
|
@work_queue = Queue.new
|
17
|
-
@
|
18
|
-
|
19
|
-
@on_error =
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
run
|
14
|
+
@work_threads = 8.times.collect { |i| make_work_thread }
|
15
|
+
|
16
|
+
@on_error =
|
17
|
+
lambda do |where, err|
|
18
|
+
puts "-" * 80
|
19
|
+
p where
|
20
|
+
p err
|
21
|
+
puts err.backtrace
|
22
|
+
puts "-" * 80
|
23
|
+
end
|
28
24
|
end
|
29
25
|
|
30
26
|
def enqueue(batch)
|
@@ -39,44 +35,46 @@ module Tresse
|
|
39
35
|
@on_error = block
|
40
36
|
end
|
41
37
|
|
42
|
-
|
43
|
-
|
44
|
-
def run
|
45
|
-
|
46
|
-
@max_work_threads.times { |i| @thread_queue << i }
|
38
|
+
def max_work_thread_count
|
47
39
|
|
48
|
-
|
49
|
-
|
50
|
-
begin
|
40
|
+
@work_threads.size
|
41
|
+
end
|
51
42
|
|
52
|
-
|
53
|
-
batch = @work_queue.pop
|
43
|
+
def max_work_thread_count=(i)
|
54
44
|
|
55
|
-
|
45
|
+
i0 = @work_threads.size
|
56
46
|
|
57
|
-
|
47
|
+
@work_threads << make_work_thread while @work_threads.size < i
|
48
|
+
@work_threads.pop while @work_threads.size > i
|
58
49
|
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
50
|
+
i
|
63
51
|
end
|
64
52
|
|
65
|
-
|
53
|
+
protected
|
54
|
+
|
55
|
+
def make_work_thread
|
66
56
|
|
67
57
|
Thread.new do
|
68
|
-
begin
|
69
58
|
|
70
|
-
|
71
|
-
|
59
|
+
t = Thread.current
|
60
|
+
t[:tresse] = true
|
72
61
|
|
73
|
-
|
62
|
+
loop do
|
63
|
+
begin
|
74
64
|
|
75
|
-
|
65
|
+
batch = @work_queue.pop
|
76
66
|
|
77
|
-
|
67
|
+
unless @work_threads.include?(t)
|
68
|
+
@work_queue << batch
|
69
|
+
break
|
70
|
+
end
|
78
71
|
|
79
|
-
|
72
|
+
batch.process
|
73
|
+
|
74
|
+
rescue => err
|
75
|
+
|
76
|
+
@on_error.call(:in_worker_thread, err)
|
77
|
+
end
|
80
78
|
end
|
81
79
|
end
|
82
80
|
end
|
@@ -88,122 +86,153 @@ module Tresse
|
|
88
86
|
class Batch
|
89
87
|
|
90
88
|
attr_reader :group
|
91
|
-
attr_reader :
|
89
|
+
attr_reader :map_index
|
90
|
+
attr_accessor :value
|
92
91
|
|
93
92
|
def initialize(group, block_or_group)
|
94
93
|
|
95
94
|
@group = group
|
96
95
|
@bog = block_or_group
|
97
96
|
|
98
|
-
@
|
97
|
+
@map_index = -1
|
99
98
|
@value = nil
|
100
99
|
end
|
101
100
|
|
102
101
|
def process
|
103
102
|
|
104
|
-
@
|
105
|
-
@group.send(:
|
103
|
+
@map_index += 1
|
104
|
+
@group.send(:receive, self)
|
106
105
|
end
|
107
106
|
|
108
|
-
|
109
|
-
|
110
|
-
def generate
|
107
|
+
def source
|
111
108
|
|
112
109
|
args = [ group ] + [ nil ] * 7
|
113
110
|
args = args[0, @bog.method(:call).arity]
|
114
111
|
|
115
112
|
@value = @bog.call(*args)
|
116
113
|
end
|
114
|
+
|
115
|
+
def map(type, block)
|
116
|
+
|
117
|
+
args = [ @value, self ]
|
118
|
+
args = args[0, block.method(:call).arity.abs]
|
119
|
+
|
120
|
+
r = block.call(*args)
|
121
|
+
|
122
|
+
@value = r if type == :map
|
123
|
+
end
|
117
124
|
end
|
118
125
|
|
119
126
|
class Group
|
120
127
|
|
121
128
|
attr_accessor :name
|
122
|
-
attr_reader :batches
|
129
|
+
#attr_reader :batches
|
123
130
|
|
124
|
-
def initialize(name)
|
131
|
+
def initialize(name=nil)
|
125
132
|
|
126
133
|
@name = name
|
127
134
|
|
128
135
|
@batches = []
|
129
|
-
@
|
136
|
+
@launched = false
|
137
|
+
@maps = [ nil ]
|
130
138
|
|
131
|
-
@
|
132
|
-
@
|
133
|
-
@
|
139
|
+
@reduce = nil
|
140
|
+
@reduce_batches = []
|
141
|
+
@reduction_queue = Queue.new
|
134
142
|
end
|
135
143
|
|
136
144
|
#
|
137
|
-
#
|
145
|
+
# sourcing methods
|
138
146
|
|
139
|
-
def
|
147
|
+
def source(o=nil, &block)
|
140
148
|
|
141
149
|
batch = Tresse::Batch.new(self, o ? o : block)
|
142
150
|
|
143
151
|
@batches << batch
|
144
|
-
|
152
|
+
|
153
|
+
self
|
145
154
|
end
|
146
155
|
|
147
156
|
#
|
148
|
-
#
|
157
|
+
# mapping
|
149
158
|
|
150
159
|
def each(&block)
|
151
160
|
|
152
|
-
|
161
|
+
do_map(:each, block)
|
162
|
+
end
|
153
163
|
|
154
|
-
|
164
|
+
def map(&block)
|
165
|
+
|
166
|
+
do_map(:map, block)
|
155
167
|
end
|
156
168
|
|
157
169
|
#
|
158
|
-
#
|
170
|
+
# reducing
|
171
|
+
|
172
|
+
def reduce(target, &block)
|
173
|
+
|
174
|
+
do_reduce(target, block)
|
175
|
+
end
|
176
|
+
alias inject reduce
|
159
177
|
|
160
|
-
def
|
178
|
+
def flatten
|
161
179
|
|
162
|
-
|
180
|
+
do_reduce([], lambda { |a, e| a.concat(e) })
|
181
|
+
end
|
182
|
+
alias values flatten
|
183
|
+
|
184
|
+
protected
|
185
|
+
|
186
|
+
def do_map(type, block)
|
163
187
|
|
164
|
-
@
|
188
|
+
@maps << [ type, block ]
|
189
|
+
|
190
|
+
launch
|
191
|
+
|
192
|
+
self
|
165
193
|
end
|
166
|
-
alias reduce inject
|
167
194
|
|
168
|
-
def
|
195
|
+
def do_reduce(target, block)
|
169
196
|
|
170
|
-
@
|
197
|
+
@reduce = [ target, block ]
|
171
198
|
|
172
|
-
|
199
|
+
launch
|
200
|
+
|
201
|
+
@reduction_queue.pop
|
173
202
|
end
|
174
|
-
alias map collect
|
175
203
|
|
176
|
-
|
204
|
+
def launch
|
205
|
+
|
206
|
+
return if @launched == true
|
207
|
+
@launched = true
|
177
208
|
|
178
|
-
|
209
|
+
@batches.each { |b| Tresse.enqueue(b) }
|
210
|
+
end
|
211
|
+
|
212
|
+
def receive(batch)
|
179
213
|
|
180
|
-
if batch.
|
181
|
-
batch.
|
214
|
+
if batch.map_index == 0
|
215
|
+
batch.source
|
182
216
|
Tresse.enqueue(batch)
|
183
|
-
elsif
|
184
|
-
|
185
|
-
args = args[0, e.method(:call).arity.abs]
|
186
|
-
e.call(*args)
|
217
|
+
elsif m = @maps[batch.map_index]
|
218
|
+
batch.map(*m)
|
187
219
|
Tresse.enqueue(batch)
|
188
220
|
else
|
189
|
-
|
221
|
+
queue_for_reduction(batch)
|
190
222
|
end
|
191
223
|
end
|
192
224
|
|
193
|
-
def
|
225
|
+
def queue_for_reduction(batch)
|
194
226
|
|
195
|
-
@
|
227
|
+
@reduce_batches << batch
|
196
228
|
|
197
|
-
return if @
|
229
|
+
return if @reduce_batches.size < @batches.size
|
230
|
+
return unless @reduce
|
198
231
|
|
199
232
|
es = @batches.collect(&:value)
|
233
|
+
target, block = @reduce
|
200
234
|
|
201
|
-
@
|
202
|
-
if @final.is_a?(Array)
|
203
|
-
es.inject(@final[0], &@final[1])
|
204
|
-
else
|
205
|
-
es.collect(&@final)
|
206
|
-
end
|
235
|
+
@reduction_queue << es.inject(target, &block)
|
207
236
|
end
|
208
237
|
end
|
209
238
|
end
|
data/tresse.gemspec
CHANGED
@@ -13,10 +13,10 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.homepage = 'http://github.com/jmettraux/tresse'
|
14
14
|
#s.rubyforge_project = 'rufus'
|
15
15
|
s.license = 'MIT'
|
16
|
-
s.summary = 'a stupid
|
16
|
+
s.summary = 'a stupid source+map+reduce thing'
|
17
17
|
|
18
18
|
s.description = %{
|
19
|
-
a poorly thought out and stupid
|
19
|
+
a poorly thought out and stupid source+map+reduce contraption
|
20
20
|
}.strip
|
21
21
|
|
22
22
|
#s.files = `git ls-files`.split("\n")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tresse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.8'
|
27
|
-
description: a poorly thought out and stupid
|
27
|
+
description: a poorly thought out and stupid source+map+reduce contraption
|
28
28
|
email:
|
29
29
|
- jmettraux@gmail.com
|
30
30
|
executables: []
|
@@ -61,5 +61,5 @@ rubyforge_project:
|
|
61
61
|
rubygems_version: 2.5.2.3
|
62
62
|
signing_key:
|
63
63
|
specification_version: 4
|
64
|
-
summary: a stupid
|
64
|
+
summary: a stupid source+map+reduce thing
|
65
65
|
test_files: []
|