rbbt-util 5.20.5 → 5.20.6
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/lib/rbbt/rest/client/get.rb +30 -0
- data/lib/rbbt/rest/client/step.rb +67 -74
- data/lib/rbbt/tsv/parallel/traverse.rb +4 -3
- data/lib/rbbt/util/log.rb +0 -2
- data/lib/rbbt/util/misc/development.rb +36 -0
- data/lib/rbbt/util/misc/inspect.rb +1 -1
- data/lib/rbbt/util/misc/multipart_payload.rb +27 -22
- data/lib/rbbt/util/misc/pipes.rb +21 -9
- data/lib/rbbt/workflow/step/dependencies.rb +11 -161
- data/lib/rbbt/workflow/step/run.rb +1 -2
- data/share/rbbt_commands/workflow/info +2 -2
- data/share/rbbt_commands/workflow/prov +0 -2
- data/share/rbbt_commands/workflow/server +4 -3
- data/test/rbbt/util/misc/test_multipart_payload.rb +202 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5413d3d8418a3823e584e819c00d387d4f1cf756
|
4
|
+
data.tar.gz: 239e68cae4bb62da2e5db9a50e11e9e5fb916e2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d646cab93661b4328ba21da388a7726064dc6ef1505e1bb8536f4d15ea53a9c9a307eb38454bca061ee3680e7b1b2b2c418e07d83d1c72fb813075cab9944176
|
7
|
+
data.tar.gz: f63f8e7912aa7dd295c44cdc344f780198baf553103cc7855beed580fba2cde5a0e0755138b59aac661fb1e1dd2212042bb949dc73d92bed5989922b4093a7c4
|
data/lib/rbbt/rest/client/get.rb
CHANGED
@@ -118,4 +118,34 @@ class WorkflowRESTClient
|
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
|
+
def self.stream_job(task_url, task_params, stream_input, cache_type = :exec)
|
122
|
+
require 'rbbt/util/misc/multipart_payload'
|
123
|
+
WorkflowRESTClient.capture_exception do
|
124
|
+
Log.debug{ "RestClient stream #{Process.pid}: #{ task_url } #{stream_input} #{cache_type} - #{Misc.fingerprint task_params}" }
|
125
|
+
res = RbbtMutiplartPayload.issue task_url, task_params, stream_input, nil, nil, true
|
126
|
+
type = res.gets
|
127
|
+
case type.strip
|
128
|
+
when "LOCATION"
|
129
|
+
@url = res.gets
|
130
|
+
@url.sub!(/\?.*/,'')
|
131
|
+
WorkflowRESTClient.get_raw(@url)
|
132
|
+
when /STREAM: (.*)/
|
133
|
+
@url = $1.strip
|
134
|
+
res.callback = Proc.new do
|
135
|
+
Log.medium "Done streaming result from #{@url}"
|
136
|
+
@done = true
|
137
|
+
end
|
138
|
+
res
|
139
|
+
when "BULK"
|
140
|
+
begin
|
141
|
+
res.read
|
142
|
+
ensure
|
143
|
+
@done = true
|
144
|
+
end
|
145
|
+
else
|
146
|
+
raise "What? " + type
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
121
151
|
end
|
@@ -3,11 +3,39 @@ class WorkflowRESTClient
|
|
3
3
|
|
4
4
|
attr_accessor :url, :base_url, :task, :base_name, :inputs, :result_type, :result_description, :is_exec, :stream_input
|
5
5
|
|
6
|
-
def
|
6
|
+
def initialize(base_url, task = nil, base_name = nil, inputs = nil, result_type = nil, result_description = nil, is_exec = false, stream_input = nil)
|
7
|
+
@base_url, @task, @base_name, @inputs, @result_type, @result_description, @is_exec, @stream_input = base_url, task, base_name, inputs, result_type, result_description, is_exec, stream_input
|
8
|
+
@mutex = Mutex.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(noload = false)
|
12
|
+
@mutex.synchronize do
|
13
|
+
@result ||= begin
|
14
|
+
if @is_exec
|
15
|
+
exec(noload)
|
16
|
+
elsif noload == :stream
|
17
|
+
_run_job(:stream)
|
18
|
+
else
|
19
|
+
init_job
|
20
|
+
self.load
|
21
|
+
end
|
22
|
+
ensure
|
23
|
+
@started = true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
return @result if noload == :stream
|
28
|
+
noload ? path + '?_format=raw' : @result
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def self.get_streams(inputs, stream_input = nil)
|
7
33
|
new_inputs = {}
|
8
34
|
inputs.each do |k,v|
|
35
|
+
stream = stream_input.to_s == k.to_s
|
9
36
|
if Step === v
|
10
|
-
|
37
|
+
v.run(true) and v.grace unless v.done? or v.streaming?
|
38
|
+
new_inputs[k] = (stream and (v.done? or v.streaming?)) ? TSV.get_stream(v) : v.path
|
11
39
|
else
|
12
40
|
new_inputs[k] = v
|
13
41
|
end
|
@@ -16,26 +44,14 @@ class WorkflowRESTClient
|
|
16
44
|
end
|
17
45
|
|
18
46
|
def get_streams
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def initialize(base_url, task = nil, base_name = nil, inputs = nil, result_type = nil, result_description = nil, is_exec = false, stream_input = nil)
|
24
|
-
@base_url, @task, @base_name, @inputs, @result_type, @result_description, @is_exec = base_url, task, base_name, inputs, result_type, result_description, is_exec
|
25
|
-
@mutex = Mutex.new
|
26
|
-
@stream_input = stream_input
|
27
|
-
#@inputs = RemoteStep.get_streams @inputs
|
47
|
+
return if @inputs_done
|
48
|
+
@inputs = WorkflowRESTClient::RemoteStep.get_streams @inputs, @stream_input
|
49
|
+
@inputs_done = true
|
50
|
+
@inputs
|
28
51
|
end
|
29
52
|
|
30
|
-
def
|
31
|
-
|
32
|
-
Log.low "Dupping inputs for remote #{path}"
|
33
|
-
new_inputs = {}
|
34
|
-
@inputs.each do |name,input|
|
35
|
-
new_inputs[name] = Step.dup_stream input
|
36
|
-
end
|
37
|
-
@inputs = RemoteStep.get_streams new_inputs
|
38
|
-
@dupped = true
|
53
|
+
def abort
|
54
|
+
#WorkflowRESTClient.get_json(File.join(@url, '?_update=abort')) if @url
|
39
55
|
end
|
40
56
|
|
41
57
|
def name
|
@@ -63,8 +79,12 @@ class WorkflowRESTClient
|
|
63
79
|
|
64
80
|
def status
|
65
81
|
return nil unless url or started?
|
82
|
+
return :done if @done
|
83
|
+
return :streaming if @streaming
|
66
84
|
begin
|
67
|
-
info[:status]
|
85
|
+
status = info[:status]
|
86
|
+
@done = true if status and status.to_sym == :done
|
87
|
+
status
|
68
88
|
ensure
|
69
89
|
@info = nil
|
70
90
|
end
|
@@ -103,9 +123,9 @@ class WorkflowRESTClient
|
|
103
123
|
#{{{ MANAGEMENT
|
104
124
|
|
105
125
|
def init_job(cache_type = nil, other_params = {})
|
106
|
-
Log.stack caller
|
107
126
|
cache_type = :asynchronous if cache_type.nil? and not @is_exec
|
108
127
|
cache_type = :exec if cache_type.nil?
|
128
|
+
get_streams
|
109
129
|
@name ||= Persist.memory("RemoteSteps", :workflow => self, :task => task, :jobname => @name, :inputs => inputs, :cache_type => cache_type) do
|
110
130
|
WorkflowRESTClient.post_jobname(File.join(base_url, task.to_s), inputs.merge(other_params).merge(:jobname => @name||@base_name, :_cache_type => cache_type))
|
111
131
|
end
|
@@ -130,26 +150,6 @@ class WorkflowRESTClient
|
|
130
150
|
end
|
131
151
|
end
|
132
152
|
|
133
|
-
def run(noload = false)
|
134
|
-
@mutex.synchronize do
|
135
|
-
@result ||= begin
|
136
|
-
if @is_exec
|
137
|
-
exec(noload)
|
138
|
-
elsif noload == :stream
|
139
|
-
_run_job(:stream)
|
140
|
-
else
|
141
|
-
init_job
|
142
|
-
self.load
|
143
|
-
end
|
144
|
-
ensure
|
145
|
-
@started = true
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
return @result if noload == :stream
|
150
|
-
noload ? path + '?_format=raw' : @result
|
151
|
-
end
|
152
|
-
|
153
153
|
def exec(noload = false)
|
154
154
|
@result ||= begin
|
155
155
|
if noload == :stream
|
@@ -163,6 +163,11 @@ class WorkflowRESTClient
|
|
163
163
|
end
|
164
164
|
|
165
165
|
def join
|
166
|
+
if IO === @result
|
167
|
+
res = @result
|
168
|
+
@result = nil
|
169
|
+
Misc.consume_stream(res, true)
|
170
|
+
end
|
166
171
|
sleep 0.2 unless self.done?
|
167
172
|
sleep 1 unless self.done?
|
168
173
|
sleep 3 while not self.done?
|
@@ -216,43 +221,26 @@ class WorkflowRESTClient
|
|
216
221
|
load_res get
|
217
222
|
end
|
218
223
|
|
219
|
-
def
|
220
|
-
|
221
|
-
|
224
|
+
def _run_job(cache_type = :async)
|
225
|
+
get_streams
|
226
|
+
if cache_type == :stream or cache_type == :exec and stream_input
|
222
227
|
task_url = URI.encode(File.join(base_url, task.to_s))
|
223
|
-
Log.debug{ "RestClient stream: #{ task_url } #{stream_input} #{cache_type} - #{Misc.fingerprint inputs}" }
|
224
228
|
task_params = inputs.merge(:_cache_type => cache_type, :jobname => base_name, :_format => [:string, :boolean, :tsv, :annotations].include?(result_type) ? :raw : :json)
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
@url.sub!(/\?.*/,'')
|
231
|
-
WorkflowRESTClient.get_raw(@url)
|
232
|
-
when /STREAM: (.*)/
|
233
|
-
@url = $1.strip
|
234
|
-
ConcurrentStream.setup(res)
|
235
|
-
res.callback = Proc.new do
|
236
|
-
@done = true
|
237
|
-
end
|
238
|
-
res
|
239
|
-
when "BULK"
|
240
|
-
begin
|
241
|
-
res.read
|
242
|
-
ensure
|
229
|
+
@streaming = true
|
230
|
+
io = WorkflowRESTClient.stream_job(task_url, task_params, stream_input, cache_type)
|
231
|
+
if IO === io
|
232
|
+
ConcurrentStream.setup(io)
|
233
|
+
io.add_callback do
|
243
234
|
@done = true
|
235
|
+
@streaming = false
|
244
236
|
end
|
245
237
|
else
|
246
|
-
|
238
|
+
@done = true
|
239
|
+
@streaming = false
|
247
240
|
end
|
241
|
+
return io
|
248
242
|
end
|
249
|
-
end
|
250
243
|
|
251
|
-
def _run_job(cache_type = :async)
|
252
|
-
#if cache_type == :stream and stream_input
|
253
|
-
if cache_type == :stream or cache_type == :exec and stream_input
|
254
|
-
return _stream_job(stream_input, cache_type)
|
255
|
-
end
|
256
244
|
WorkflowRESTClient.capture_exception do
|
257
245
|
@url = URI.encode(File.join(base_url, task.to_s))
|
258
246
|
task_params = inputs.merge(:_cache_type => cache_type, :jobname => base_name, :_format => [:string, :boolean, :tsv, :annotations].include?(result_type) ? :raw : :json)
|
@@ -262,7 +250,7 @@ class WorkflowRESTClient
|
|
262
250
|
sin.write c
|
263
251
|
end
|
264
252
|
|
265
|
-
Thread.new do
|
253
|
+
post_thread = Thread.new do
|
266
254
|
bl = lambda do |rok|
|
267
255
|
rok.read_body do |c,_a, _b|
|
268
256
|
sin.write c
|
@@ -270,17 +258,20 @@ class WorkflowRESTClient
|
|
270
258
|
sin.close
|
271
259
|
end
|
272
260
|
|
261
|
+
Log.debug{ "RestClient execute: #{ url } - #{Misc.fingerprint task_params}" }
|
273
262
|
RestClient::Request.execute(:method => :post, :url => url, :payload => task_params, :block_response => bl)
|
274
263
|
end
|
275
264
|
|
276
265
|
reader = Zlib::GzipReader.new(sout)
|
277
|
-
Misc.open_pipe do |sin|
|
278
|
-
while c = reader.read(
|
266
|
+
res_io = Misc.open_pipe do |sin|
|
267
|
+
while c = reader.read(Misc::BLOCK_SIZE)
|
279
268
|
sin.write c
|
280
269
|
end
|
281
270
|
sin.close
|
282
271
|
@done = true
|
283
272
|
end
|
273
|
+
|
274
|
+
ConcurrentStream.setup(res_io, :threads => [post_thread])
|
284
275
|
end
|
285
276
|
end
|
286
277
|
|
@@ -305,6 +296,7 @@ class WorkflowRESTClient
|
|
305
296
|
end
|
306
297
|
|
307
298
|
def recursive_clean
|
299
|
+
return
|
308
300
|
begin
|
309
301
|
params = {:_update => :recursive_clean}
|
310
302
|
init_job(nil, params)
|
@@ -317,6 +309,7 @@ class WorkflowRESTClient
|
|
317
309
|
end
|
318
310
|
|
319
311
|
def clean
|
312
|
+
return
|
320
313
|
begin
|
321
314
|
params = {:_update => :clean}
|
322
315
|
init_job(nil, params)
|
@@ -54,8 +54,8 @@ module TSV
|
|
54
54
|
|
55
55
|
def self.stream_name(obj)
|
56
56
|
return "nil" if obj.nil?
|
57
|
-
filename_obj = obj.respond_to?(:filename) ? obj.filename : nil
|
58
|
-
filename_obj ||= obj.respond_to?(:path) ? obj.path : nil
|
57
|
+
#filename_obj = obj.respond_to?(:filename) ? obj.filename : nil
|
58
|
+
#filename_obj ||= obj.respond_to?(:path) ? obj.path : nil
|
59
59
|
stream_obj = obj_stream(obj) || obj
|
60
60
|
obj.class.to_s << "-" << Misc.fingerprint(stream_obj)
|
61
61
|
end
|
@@ -223,7 +223,8 @@ module TSV
|
|
223
223
|
options[:type] = :single
|
224
224
|
end
|
225
225
|
|
226
|
-
|
226
|
+
name = stream_name(obj)
|
227
|
+
Log.medium{"Traversing #{name} #{Log.color :green, "->"} #{stream_name(options[:into])}"}
|
227
228
|
begin
|
228
229
|
case obj
|
229
230
|
when TSV
|
data/lib/rbbt/util/log.rb
CHANGED
@@ -156,9 +156,7 @@ module Log
|
|
156
156
|
|
157
157
|
sev_str = severity.to_s
|
158
158
|
|
159
|
-
#prefix = time << "[" << color(severity) << sev_str << color(0)<<"]"
|
160
159
|
prefix = time << color(severity) << "[" << sev_str << "]" << color(0)
|
161
|
-
#prefix = color(severity) << time << color(0) << "[" << sev_str << "]"
|
162
160
|
message = "" << highlight << message << color(0) if severity >= INFO
|
163
161
|
str = prefix << " " << message
|
164
162
|
|
@@ -318,6 +318,42 @@ module Misc
|
|
318
318
|
end
|
319
319
|
end
|
320
320
|
|
321
|
+
def self.bootstrap_in_threads(elems, num = :current, options = {}, &block)
|
322
|
+
IndiferentHash.setup options
|
323
|
+
num = :current if num.nil?
|
324
|
+
threads = case num
|
325
|
+
when :current
|
326
|
+
10
|
327
|
+
when String
|
328
|
+
num.to_i
|
329
|
+
when Integer
|
330
|
+
if num < 100
|
331
|
+
num
|
332
|
+
else
|
333
|
+
32000 / num
|
334
|
+
end
|
335
|
+
else
|
336
|
+
raise "Parameter 'num' not understood: #{Misc.fingerprint num}"
|
337
|
+
end
|
338
|
+
|
339
|
+
|
340
|
+
options = Misc.add_defaults options, :respawn => true, :threads => threads
|
341
|
+
options = Misc.add_defaults options, :bar => "Bootstrap in #{ options[:threads] } threads: #{ Misc.fingerprint Annotated.purge(elems) }"
|
342
|
+
|
343
|
+
index = (0..elems.length-1).to_a.collect{|v| v.to_s }
|
344
|
+
TSV.traverse index, options do |pos|
|
345
|
+
elem = elems[pos.to_i]
|
346
|
+
elems.annotate elem if elems.respond_to? :annotate
|
347
|
+
begin
|
348
|
+
res = yield elem
|
349
|
+
rescue Interrupt
|
350
|
+
Log.warn "Process #{Process.pid} was aborted"
|
351
|
+
raise $!
|
352
|
+
end
|
353
|
+
res = nil unless options[:into]
|
354
|
+
res
|
355
|
+
end
|
356
|
+
end
|
321
357
|
def self.memory_use(pid=nil)
|
322
358
|
`ps -o rss -p #{pid || $$}`.strip.split.last.to_i
|
323
359
|
end
|
@@ -54,13 +54,12 @@ module RbbtMutiplartPayload
|
|
54
54
|
io.write c
|
55
55
|
end
|
56
56
|
rescue EOFError
|
57
|
+
io.write "\r\n"
|
57
58
|
end
|
58
|
-
content.close
|
59
59
|
end
|
60
60
|
|
61
61
|
def self.close_stream(io)
|
62
62
|
io.write "--" + BOUNDARY + "--" + EOL + EOL
|
63
|
-
io.close
|
64
63
|
end
|
65
64
|
|
66
65
|
def self.post_data_stream(inputs = nil, stream_input = nil, stream_io = nil, stream_filename = nil)
|
@@ -88,16 +87,12 @@ module RbbtMutiplartPayload
|
|
88
87
|
|
89
88
|
RbbtMutiplartPayload.add_stream(sin, stream_input.to_s, stream_io, stream_filename) if stream_input
|
90
89
|
RbbtMutiplartPayload.close_stream(sin)
|
91
|
-
|
92
|
-
sin.close unless sin.closed?
|
93
90
|
end
|
94
91
|
end
|
95
92
|
|
96
93
|
def self.issue(url, inputs = nil, stream_input = nil, stream_io = nil, stream_filename = nil, report_type = false)
|
97
94
|
|
98
95
|
uri = URI(url)
|
99
|
-
req = Net::HTTP::Post.new(uri.path)
|
100
|
-
|
101
96
|
IndiferentHash.setup(inputs)
|
102
97
|
|
103
98
|
if stream_input
|
@@ -112,37 +107,47 @@ module RbbtMutiplartPayload
|
|
112
107
|
end
|
113
108
|
end
|
114
109
|
|
115
|
-
|
110
|
+
post_data_stream = RbbtMutiplartPayload.post_data_stream inputs, stream_input, stream_io, stream_filename
|
116
111
|
|
112
|
+
jobname = inputs["jobname"]
|
113
|
+
|
114
|
+
req = Net::HTTP::Post.new(uri.path)
|
117
115
|
if stream_input
|
118
116
|
req.content_type = "multipart/form-data; boundary=" + RbbtMutiplartPayload::BOUNDARY + '; stream=' + stream_input.to_s
|
119
|
-
req.body_stream =
|
120
|
-
req.add_field "Transfer-Encoding", "chunked"
|
117
|
+
req.body_stream = post_data_stream
|
121
118
|
else
|
122
119
|
req.content_type = "multipart/form-data; boundary=" + RbbtMutiplartPayload::BOUNDARY
|
123
|
-
req.body =
|
120
|
+
req.body = post_data_stream.read
|
124
121
|
end
|
125
122
|
|
123
|
+
req.add_field "Transfer-Encoding", 'chunked'
|
124
|
+
req.add_field "RBBT_ID", (jobname || "No name")
|
126
125
|
Misc.open_pipe do |sin|
|
127
126
|
Net::HTTP.start(uri.hostname, uri.port) do |http|
|
128
127
|
http.request(req) do |res|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
128
|
+
if Net::HTTPSuccess === res
|
129
|
+
url_path = res["RBBT-STREAMING-JOB-URL"]
|
130
|
+
if Net::HTTPRedirection === res
|
131
|
+
Log.medium "Response recieved REDIRECT: #{ url_path }"
|
132
|
+
sin.puts "LOCATION" if report_type
|
133
|
+
sin.write res["location"]
|
134
|
+
elsif stream_input and url_path
|
135
|
+
Log.medium "Response recieved STREAM: #{ url_path }"
|
136
|
+
url = URI::HTTP.build(:host => uri.hostname, :post => uri.port, :path => url_path)
|
137
|
+
sin.puts "STREAM: #{url.to_s}" if report_type
|
138
|
+
Log.medium "Read body: #{ url_path }"
|
139
|
+
res.read_body(sin)
|
140
|
+
Log.medium "Read body DONE: #{ url_path }"
|
141
|
+
else
|
142
|
+
Log.medium "Response recieved BULK: #{ url_path }"
|
143
|
+
sin.puts "BULK" if report_type
|
144
|
+
sin.write res.body
|
138
145
|
end
|
139
146
|
else
|
140
|
-
|
141
|
-
sin.write res.body
|
147
|
+
raise "Error: #{res.code}"
|
142
148
|
end
|
143
149
|
end
|
144
150
|
end
|
145
151
|
end
|
146
152
|
end
|
147
|
-
|
148
153
|
end
|
data/lib/rbbt/util/misc/pipes.rb
CHANGED
@@ -54,27 +54,32 @@ module Misc
|
|
54
54
|
sout, sin = Misc.pipe
|
55
55
|
|
56
56
|
if do_fork
|
57
|
+
|
57
58
|
parent_pid = Process.pid
|
58
59
|
pid = Process.fork {
|
59
60
|
purge_pipes(sin)
|
60
61
|
sout.close
|
61
62
|
begin
|
63
|
+
|
62
64
|
yield sin
|
63
65
|
sin.close if close and not sin.closed?
|
64
|
-
|
66
|
+
|
67
|
+
rescue Exception
|
65
68
|
Log.exception $!
|
66
69
|
Process.kill :INT, parent_pid
|
67
70
|
Kernel.exit! -1
|
68
71
|
end
|
69
72
|
Kernel.exit! 0
|
70
73
|
}
|
71
|
-
|
74
|
+
|
72
75
|
ConcurrentStream.setup sout, :pids => [pid]
|
73
76
|
else
|
74
77
|
thread = Thread.new(Thread.current) do |parent|
|
75
78
|
begin
|
79
|
+
|
76
80
|
yield sin
|
77
81
|
sin.close if close and not sin.closed?
|
82
|
+
|
78
83
|
rescue Aborted
|
79
84
|
Log.medium "Aborted open_pipe: #{$!.message}"
|
80
85
|
rescue Exception
|
@@ -83,8 +88,10 @@ module Misc
|
|
83
88
|
raise $!
|
84
89
|
end
|
85
90
|
end
|
91
|
+
|
86
92
|
ConcurrentStream.setup sout, :threads => [thread]
|
87
93
|
end
|
94
|
+
|
88
95
|
sout
|
89
96
|
end
|
90
97
|
|
@@ -147,6 +154,8 @@ module Misc
|
|
147
154
|
out_pipes << sout
|
148
155
|
end
|
149
156
|
|
157
|
+
filename = stream.filename if stream.respond_to? :filename
|
158
|
+
|
150
159
|
splitter_thread = Thread.new(Thread.current) do |parent|
|
151
160
|
begin
|
152
161
|
|
@@ -156,9 +165,9 @@ module Misc
|
|
156
165
|
|
157
166
|
in_pipes.each_with_index do |sin,i|
|
158
167
|
begin
|
159
|
-
sin.write block
|
168
|
+
sin.write block
|
160
169
|
rescue IOError
|
161
|
-
Log.
|
170
|
+
Log.error("Tee stream #{i} #{Misc.fingerprint stream} IOError: #{$!.message}");
|
162
171
|
skip[i] = true
|
163
172
|
end unless skip[i]
|
164
173
|
end
|
@@ -169,6 +178,7 @@ module Misc
|
|
169
178
|
in_pipes.each do |sin|
|
170
179
|
sin.close unless sin.closed?
|
171
180
|
end
|
181
|
+
|
172
182
|
stream.join if stream.respond_to? :join
|
173
183
|
rescue Aborted, Interrupt
|
174
184
|
stream.abort if stream.respond_to? :abort
|
@@ -188,7 +198,7 @@ module Misc
|
|
188
198
|
end
|
189
199
|
|
190
200
|
out_pipes.each do |sout|
|
191
|
-
ConcurrentStream.setup sout, :threads => splitter_thread
|
201
|
+
ConcurrentStream.setup sout, :threads => splitter_thread, :filename => filename
|
192
202
|
end
|
193
203
|
|
194
204
|
out_pipes
|
@@ -205,13 +215,15 @@ module Misc
|
|
205
215
|
stream.clear
|
206
216
|
end
|
207
217
|
tee1, *rest = Misc.tee_stream stream_dup, num + 1
|
208
|
-
stream.reopen(tee1)
|
209
218
|
rest
|
210
219
|
end
|
211
220
|
|
221
|
+
def Misc.dup_stream (stream)
|
222
|
+
dup_stream_multiple(stream, 1).first
|
223
|
+
end
|
224
|
+
|
212
225
|
class << self
|
213
226
|
alias tee_stream tee_stream_thread_multiple
|
214
|
-
alias dup_stream dup_stream_multiple
|
215
227
|
end
|
216
228
|
|
217
229
|
def self.read_full_stream(io)
|
@@ -254,8 +266,8 @@ module Misc
|
|
254
266
|
io.sync = true
|
255
267
|
|
256
268
|
begin
|
257
|
-
while
|
258
|
-
into <<
|
269
|
+
while c = io.readpartial(BLOCK_SIZE)
|
270
|
+
into << c if into
|
259
271
|
end
|
260
272
|
rescue EOFError
|
261
273
|
end
|
@@ -79,7 +79,7 @@ class Step
|
|
79
79
|
|
80
80
|
job.clean if job.error? or job.aborted? or (job.started? and not job.running? and not job.error?)
|
81
81
|
|
82
|
-
job.dup_inputs
|
82
|
+
job.dup_inputs unless job.done? or job.started?
|
83
83
|
|
84
84
|
raise DependencyError, job if job.error?
|
85
85
|
end
|
@@ -157,64 +157,18 @@ class Step
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
#def consolidate_dependencies(path_deps = {})
|
161
|
-
# return false if @consolidated or dependencies.nil? or dependencies.empty?
|
162
|
-
# consolidated_deps = dependencies.collect do |dep|
|
163
|
-
# dep.consolidate_dependencies(path_deps)
|
164
|
-
# path = dep.path
|
165
|
-
# path_deps[path] ||= dep
|
166
|
-
# end
|
167
|
-
# dependencies.replace consolidated_deps
|
168
|
-
# @consolidated = true
|
169
|
-
#end
|
170
|
-
|
171
|
-
#def prepare_dependencies
|
172
|
-
# dep_step = {}
|
173
|
-
|
174
|
-
# all_deps = rec_dependencies + [self]
|
175
|
-
|
176
|
-
# seen_paths = Set.new
|
177
|
-
# all_deps.uniq.each do |step|
|
178
|
-
# next if seen_paths.include? step.path
|
179
|
-
# Step.prepare_for_execution(step)
|
180
|
-
# seen_paths << step.path
|
181
|
-
# step.dependencies.each do |step_dep|
|
182
|
-
# dep_step[step_dep.path] ||= []
|
183
|
-
# dep_step[step_dep.path] << step_dep
|
184
|
-
# end
|
185
|
-
# end
|
186
|
-
|
187
|
-
# seen_paths = Set.new
|
188
|
-
# rec_dependencies.uniq.each do |step|
|
189
|
-
# next if seen_paths.include? step.path
|
190
|
-
# = {} seen_paths << step.path
|
191
|
-
# execute_dependency(step)
|
192
|
-
# if step.streaming? and step.result
|
193
|
-
# if dep_step[step.path] and dep_step[step.path].length > 1
|
194
|
-
# stream = step.result
|
195
|
-
# other_steps = dep_step[step.path] - [step]
|
196
|
-
# copies = Misc.dup_stream_multiple(stream, other_steps.length)
|
197
|
-
# other_steps.zip(copies).each do |other,dupped_stream|
|
198
|
-
# other.instance_variable_set(:@result, dupped_stream)
|
199
|
-
# end
|
200
|
-
# end
|
201
|
-
# end
|
202
|
-
# end
|
203
|
-
|
204
|
-
# Step.purge_stream_cache
|
205
|
-
#end
|
206
|
-
|
207
160
|
def execute_and_dup(step, dep_step, log = true)
|
208
161
|
dup = step.result.nil?
|
209
162
|
execute_dependency(step, log)
|
210
163
|
if dup and step.streaming? and not step.result.nil?
|
211
164
|
if dep_step[step.path] and dep_step[step.path].length > 1
|
212
165
|
stream = step.result
|
213
|
-
other_steps = dep_step[step.path]
|
214
|
-
|
166
|
+
other_steps = dep_step[step.path]
|
167
|
+
return unless other_steps.length > 1
|
168
|
+
copies = Misc.tee_stream_thread_multiple(stream, other_steps.length)
|
215
169
|
log_dependency_exec(step, "duplicating #{copies.length}")
|
216
170
|
other_steps.zip(copies).each do |other,dupped_stream|
|
217
|
-
other.instance_variable_set(
|
171
|
+
other.instance_variable_set("@result", dupped_stream)
|
218
172
|
end
|
219
173
|
end
|
220
174
|
end
|
@@ -233,10 +187,10 @@ class Step
|
|
233
187
|
end
|
234
188
|
when :bootstrap
|
235
189
|
cpus = rest.nil? ? nil : rest.first
|
236
|
-
cpus =
|
190
|
+
cpus = 5 if cpus.nil?
|
237
191
|
cpus = list.length / 2 if cpus > list.length / 2
|
238
192
|
|
239
|
-
Misc.bootstrap(list, cpus, :bar => "Bootstrapping dependencies for #{path}", :
|
193
|
+
Misc.bootstrap(list, cpus, :bar => "Bootstrapping dependencies for #{path}", :respawn => :always) do |dep|
|
240
194
|
dep.produce
|
241
195
|
nil
|
242
196
|
end
|
@@ -280,7 +234,7 @@ class Step
|
|
280
234
|
dep_step[step_dep.path] << step_dep
|
281
235
|
end
|
282
236
|
end
|
283
|
-
|
237
|
+
|
284
238
|
self.dup_inputs
|
285
239
|
|
286
240
|
required_dep_paths = []
|
@@ -325,18 +279,18 @@ class Step
|
|
325
279
|
execute_and_dup(step, dep_step, false)
|
326
280
|
end
|
327
281
|
|
328
|
-
Log.medium "Computing pre dependencies: #{Misc.fingerprint(compute_pre_deps)} - #{Log.color :blue, self.path}" if
|
282
|
+
Log.medium "Computing pre dependencies: #{Misc.fingerprint(compute_pre_deps)} - #{Log.color :blue, self.path}" if compute_pre_deps.any?
|
329
283
|
compute_pre_deps.each do |type,list|
|
330
284
|
run_compute_dependencies(type, list, dep_step)
|
331
285
|
end
|
332
286
|
|
333
|
-
Log.medium "Processing last dependencies: #{Misc.fingerprint(last_deps)} - #{Log.color :blue, self.path}" if
|
287
|
+
Log.medium "Processing last dependencies: #{Misc.fingerprint(last_deps)} - #{Log.color :blue, self.path}" if last_deps.any?
|
334
288
|
last_deps.each do |step|
|
335
289
|
next if compute_deps.include? step
|
336
290
|
execute_and_dup(step, dep_step)
|
337
291
|
end
|
338
292
|
|
339
|
-
Log.medium "Computing last dependencies: #{Misc.fingerprint(compute_last_deps)} - #{Log.color :blue, self.path}" if
|
293
|
+
Log.medium "Computing last dependencies: #{Misc.fingerprint(compute_last_deps)} - #{Log.color :blue, self.path}" if compute_last_deps.any?
|
340
294
|
compute_last_deps.each do |type,list|
|
341
295
|
run_compute_dependencies(type, list, dep_step)
|
342
296
|
end
|
@@ -350,108 +304,4 @@ class Step
|
|
350
304
|
kill_children
|
351
305
|
end
|
352
306
|
|
353
|
-
#def run_dependencies
|
354
|
-
# @seen ||= []
|
355
|
-
# seen_paths ||= Set.new
|
356
|
-
#
|
357
|
-
# consolidate_dependencies
|
358
|
-
# dependencies.uniq.each do |dependency|
|
359
|
-
# dependency_path = dependency.path
|
360
|
-
# next if seen_paths.include? dependency_path
|
361
|
-
# @seen.concat dependency.rec_dependencies
|
362
|
-
# seen_paths.union(dependency.rec_dependencies.collect{|d| d.path})
|
363
|
-
# @seen << dependency
|
364
|
-
# seen_paths << dependency_path
|
365
|
-
# end
|
366
|
-
|
367
|
-
# @seen.uniq!
|
368
|
-
# @seen.delete self
|
369
|
-
|
370
|
-
# return if @seen.empty?
|
371
|
-
|
372
|
-
# log :dependencies, "#{Log.color :magenta, "Dependencies"} for step #{Log.color :yellow, task.name.to_s || ""}"
|
373
|
-
|
374
|
-
# @seen.each do |dependency|
|
375
|
-
# Step.prepare_for_execution(dependency)
|
376
|
-
# end
|
377
|
-
|
378
|
-
# pre_deps = []
|
379
|
-
# compute_pre_deps = {}
|
380
|
-
# last_deps = []
|
381
|
-
# compute_last_deps = {}
|
382
|
-
# @seen.each do |dependency|
|
383
|
-
# if dependencies.include?(dependency) and dependency.inputs.flatten.select{|i| Step === i}.any?
|
384
|
-
# if ComputeDependency === dependency
|
385
|
-
# compute_last_deps[dependency.compute] ||= []
|
386
|
-
# compute_last_deps[dependency.compute] << dependency
|
387
|
-
# else
|
388
|
-
# last_deps << dependency
|
389
|
-
# end
|
390
|
-
# else
|
391
|
-
# if ComputeDependency === dependency
|
392
|
-
# compute_pre_deps[dependency.compute] ||= []
|
393
|
-
# compute_pre_deps[dependency.compute] << dependency
|
394
|
-
# else
|
395
|
-
# pre_deps << dependency if dependencies.include?(dependency)
|
396
|
-
# end
|
397
|
-
# end
|
398
|
-
# end
|
399
|
-
|
400
|
-
# pre_deps.each do |dependency|
|
401
|
-
# dependency.dup_inputs
|
402
|
-
# execute_dependency(dependency)
|
403
|
-
# end
|
404
|
-
|
405
|
-
# compute_pre_deps.each do |type,list|
|
406
|
-
# if Array === type
|
407
|
-
# type, *rest = type
|
408
|
-
# end
|
409
|
-
|
410
|
-
# case type
|
411
|
-
# when :bootstrap
|
412
|
-
# cpus = rest.nil? ? nil : rest.first
|
413
|
-
# cpus = 10 if cpus.nil?
|
414
|
-
|
415
|
-
# list.each do |dependency|
|
416
|
-
# dependency.dup_inputs
|
417
|
-
# end
|
418
|
-
|
419
|
-
# Misc.bootstrap(list, cpus, :bar => "Bootstrapping dependencies for #{path}", :_respawn => :always) do |dep|
|
420
|
-
# dep.produce
|
421
|
-
# nil
|
422
|
-
# end
|
423
|
-
# else
|
424
|
-
# list.each do |dependency|
|
425
|
-
# dependency.dup_inputs
|
426
|
-
# execute_dependency(dependency)
|
427
|
-
# end
|
428
|
-
# end
|
429
|
-
# end
|
430
|
-
|
431
|
-
# last_deps.each do |dependency|
|
432
|
-
# dependency.dup_inputs
|
433
|
-
# end
|
434
|
-
|
435
|
-
# last_deps.each do |dependency|
|
436
|
-
# execute_dependency(dependency)
|
437
|
-
# end
|
438
|
-
|
439
|
-
# compute_last_deps.each do |type,list|
|
440
|
-
# case type
|
441
|
-
# when :_bootstrap
|
442
|
-
# list.each do |dependency|
|
443
|
-
# dependency.dup_inputs
|
444
|
-
# end
|
445
|
-
# Misc.bootstrap(list, 3, :bar => "Boostrapping dependencies for #{path}", :respawn => :always) do |dependency|
|
446
|
-
# dependency.produce
|
447
|
-
# nil
|
448
|
-
# end
|
449
|
-
# else
|
450
|
-
# list.each do |dependency|
|
451
|
-
# dependency.dup_inputs
|
452
|
-
# execute_dependency(dependency)
|
453
|
-
# end
|
454
|
-
# end
|
455
|
-
# end
|
456
|
-
#end
|
457
307
|
end
|
@@ -6,7 +6,7 @@ class Step
|
|
6
6
|
|
7
7
|
def get_stream
|
8
8
|
@mutex.synchronize do
|
9
|
-
Log.low "Getting stream from #{path} #{!@saved_stream} [#{object_id}]"
|
9
|
+
Log.low "Getting stream from #{path} #{!@saved_stream} [#{object_id}-#{Misc.fingerprint(@result)}]"
|
10
10
|
begin
|
11
11
|
return nil if @saved_stream
|
12
12
|
if IO === @result
|
@@ -113,7 +113,6 @@ class Step
|
|
113
113
|
:clean_name => clean_name,
|
114
114
|
})
|
115
115
|
|
116
|
-
dup_inputs
|
117
116
|
begin
|
118
117
|
run_dependencies
|
119
118
|
rescue Exception
|
@@ -125,8 +125,8 @@ if recursive
|
|
125
125
|
|
126
126
|
while deps.any? do
|
127
127
|
dep = deps.shift
|
128
|
-
inputs = inputs.merge(dep.info[:inputs])
|
129
|
-
deps.concat dep.info[:dependencies].collect{|v| get_step v.last }
|
128
|
+
inputs = inputs.merge(dep.info[:inputs] || {})
|
129
|
+
deps.concat (dep.info[:dependencies] || []).collect{|v| get_step v.last }
|
130
130
|
end
|
131
131
|
|
132
132
|
inputs.each do |input,value|
|
@@ -64,7 +64,7 @@ TmpFile.with_file do |app_dir|
|
|
64
64
|
ENV["RBBT_VIEWS_DIR"] = options[:views] if options.include?(:views)
|
65
65
|
|
66
66
|
if options[:stream]
|
67
|
-
raise "No streaming available for any server other than puma" unless options[:server]
|
67
|
+
raise "No streaming available for any server other than puma" unless true or options[:server].include? 'puma'
|
68
68
|
ENV["RBBT_WORKFLOW_TASK_STREAM"] = 'true'
|
69
69
|
end
|
70
70
|
|
@@ -81,9 +81,10 @@ TmpFile.with_file do |app_dir|
|
|
81
81
|
|
82
82
|
case server
|
83
83
|
when 'unicorn'
|
84
|
-
`unicorn -c #{ Rbbt.share['unicorn.rb'].find } '#{config_ru_file}' -p #{options[:port] || "2887"}`
|
84
|
+
`env RBBT_LOG=#{Log.severity.to_s} unicorn -c #{ Rbbt.share['unicorn.rb'].find } '#{config_ru_file}' -p #{options[:port] || "2887"}`
|
85
85
|
when 'puma_alt'
|
86
|
-
|
86
|
+
#`puma '#{config_ru_file}' -p #{options[:Port] || "2887"} -w 3 -t 8:32 --preload`
|
87
|
+
`env RBBT_LOG=#{Log.severity.to_s} puma '#{config_ru_file}' -p #{options[:Port] || "2887"} -w 20 -t 10:160 --preload`
|
87
88
|
else
|
88
89
|
options[:config] = config_ru_file
|
89
90
|
Rack::Server.start(options)
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_helper.rb')
|
2
|
+
require 'rbbt/util/misc/multipart_payload'
|
3
|
+
|
4
|
+
class TestMultipartPayload < Test::Unit::TestCase
|
5
|
+
|
6
|
+
URL='http://localhost:2887/Echo'
|
7
|
+
def _test_post_data_stream
|
8
|
+
content =<<-EOF
|
9
|
+
Line 1
|
10
|
+
Line 2
|
11
|
+
Line 3
|
12
|
+
END
|
13
|
+
EOF
|
14
|
+
mutipart =<<-EOF
|
15
|
+
--Rbbt_Param_Stream<>
|
16
|
+
Content-Disposition: form-data; name="input1"<>
|
17
|
+
Content-Transfer-Encoding: binary<>
|
18
|
+
Content-Type: text/plain<>
|
19
|
+
<>
|
20
|
+
Input1<>
|
21
|
+
--Rbbt_Param_Stream<>
|
22
|
+
Content-Disposition: form-data; name="input2"<>
|
23
|
+
Content-Transfer-Encoding: binary<>
|
24
|
+
Content-Type: text/plain<>
|
25
|
+
<>
|
26
|
+
Input2<>
|
27
|
+
--Rbbt_Param_Stream<>
|
28
|
+
Content-Disposition: form-data; name="stream_input"<>
|
29
|
+
Content-Transfer-Encoding: binary<>
|
30
|
+
Content-Type: text/plain<>
|
31
|
+
<>
|
32
|
+
Line 1
|
33
|
+
Line 2
|
34
|
+
Line 3
|
35
|
+
END
|
36
|
+
<>
|
37
|
+
--Rbbt_Param_Stream--<>
|
38
|
+
<>
|
39
|
+
EOF
|
40
|
+
TmpFile.with_file(content) do |tmpfile|
|
41
|
+
inputs = {}
|
42
|
+
stream_input = :stream_input
|
43
|
+
inputs[:input1] = "Input1"
|
44
|
+
inputs[:input2] = "Input2"
|
45
|
+
inputs[:stream_input] = Open.open(tmpfile)
|
46
|
+
|
47
|
+
post_data_stream = RbbtMutiplartPayload.post_data_stream(inputs, stream_input, inputs[stream_input])
|
48
|
+
assert_equal mutipart, post_data_stream.read.gsub(/\r\n/,"<>\n")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def _test_issue
|
53
|
+
content =<<-EOF
|
54
|
+
Line 1
|
55
|
+
Line 2
|
56
|
+
Line 3
|
57
|
+
END
|
58
|
+
EOF
|
59
|
+
mutipart =<<-EOF
|
60
|
+
--Rbbt_Param_Stream<>
|
61
|
+
Content-Disposition: form-data; name="input1"<>
|
62
|
+
Content-Transfer-Encoding: binary<>
|
63
|
+
Content-Type: text/plain<>
|
64
|
+
<>
|
65
|
+
Input1<>
|
66
|
+
--Rbbt_Param_Stream<>
|
67
|
+
Content-Disposition: form-data; name="input2"<>
|
68
|
+
Content-Transfer-Encoding: binary<>
|
69
|
+
Content-Type: text/plain<>
|
70
|
+
<>
|
71
|
+
Input2<>
|
72
|
+
--Rbbt_Param_Stream<>
|
73
|
+
Content-Disposition: form-data; name="stream_input"; filename="FILENAME"<>
|
74
|
+
Content-Transfer-Encoding: binary<>
|
75
|
+
Content-Type: text/plain<>
|
76
|
+
<>
|
77
|
+
Line 1
|
78
|
+
Line 2
|
79
|
+
Line 3
|
80
|
+
END
|
81
|
+
<>
|
82
|
+
--Rbbt_Param_Stream--<>
|
83
|
+
<>
|
84
|
+
DONE_PARAM_STREAM
|
85
|
+
EOF
|
86
|
+
inputs = {}
|
87
|
+
#mutipart.gsub!('<>',"\r")
|
88
|
+
stream_input = :stream_input
|
89
|
+
inputs[:input1] = "Input1"
|
90
|
+
inputs[:input2] = "Input2"
|
91
|
+
num = 50
|
92
|
+
cpus = 1
|
93
|
+
TmpFile.with_file(content) do |tmpfile|
|
94
|
+
inputs = inputs.dup
|
95
|
+
inputs[:stream_input] = File.open(tmpfile)
|
96
|
+
|
97
|
+
io = RbbtMutiplartPayload.issue(URL, inputs, stream_input)
|
98
|
+
assert_equal mutipart.sub("FILENAME", tmpfile).force_encoding("ASCII"), io.read.gsub(/\r\n/,"<>\n")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _test_issue_multiple
|
103
|
+
content =<<-EOF
|
104
|
+
Line 1
|
105
|
+
Line 2
|
106
|
+
Line 3
|
107
|
+
END
|
108
|
+
EOF
|
109
|
+
mutipart =<<-EOF
|
110
|
+
--Rbbt_Param_Stream<>
|
111
|
+
Content-Disposition: form-data; name="input1"<>
|
112
|
+
Content-Transfer-Encoding: binary<>
|
113
|
+
Content-Type: text/plain<>
|
114
|
+
<>
|
115
|
+
Input1<>
|
116
|
+
--Rbbt_Param_Stream<>
|
117
|
+
Content-Disposition: form-data; name="input2"<>
|
118
|
+
Content-Transfer-Encoding: binary<>
|
119
|
+
Content-Type: text/plain<>
|
120
|
+
<>
|
121
|
+
Input2<>
|
122
|
+
--Rbbt_Param_Stream<>
|
123
|
+
Content-Disposition: form-data; name="stream_input"; filename="FILENAME"<>
|
124
|
+
Content-Transfer-Encoding: binary<>
|
125
|
+
Content-Type: text/plain<>
|
126
|
+
<>
|
127
|
+
Line 1
|
128
|
+
Line 2
|
129
|
+
Line 3
|
130
|
+
END
|
131
|
+
<>
|
132
|
+
--Rbbt_Param_Stream--<>
|
133
|
+
<>
|
134
|
+
DONE_PARAM_STREAM
|
135
|
+
EOF
|
136
|
+
inputs = {}
|
137
|
+
stream_input = :stream_input
|
138
|
+
inputs[:input1] = "Input1"
|
139
|
+
inputs[:input2] = "Input2"
|
140
|
+
num = 100
|
141
|
+
cpus = 10
|
142
|
+
Misc.bootstrap((0..num-1).to_a, cpus) do |n|
|
143
|
+
TmpFile.with_file(content) do |tmpfile|
|
144
|
+
inputs = inputs.dup
|
145
|
+
inputs[:stream_input] = File.open(tmpfile)
|
146
|
+
|
147
|
+
io = RbbtMutiplartPayload.issue(URL, inputs, stream_input)
|
148
|
+
str = io.read
|
149
|
+
assert_equal mutipart.sub("FILENAME", tmpfile).force_encoding("ASCII"), str.gsub(/\r\n/,"<>\n")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def _test_raw
|
155
|
+
mutipart =<<-EOF
|
156
|
+
--Rbbt_Param_Stream<>
|
157
|
+
Content-Disposition: form-data; name="input1"<>
|
158
|
+
Content-Transfer-Encoding: binary<>
|
159
|
+
Content-Type: text/plain<>
|
160
|
+
<>
|
161
|
+
Input1<>
|
162
|
+
--Rbbt_Param_Stream<>
|
163
|
+
Content-Disposition: form-data; name="input2"<>
|
164
|
+
Content-Transfer-Encoding: binary<>
|
165
|
+
Content-Type: text/plain<>
|
166
|
+
<>
|
167
|
+
Input2<>
|
168
|
+
--Rbbt_Param_Stream<>
|
169
|
+
Content-Disposition: form-data; name="stream_input"; filename="FILENAME"<>
|
170
|
+
Content-Transfer-Encoding: binary<>
|
171
|
+
Content-Type: text/plain<>
|
172
|
+
<>
|
173
|
+
Line 1
|
174
|
+
Line 2
|
175
|
+
Line 3
|
176
|
+
END
|
177
|
+
<>
|
178
|
+
--Rbbt_Param_Stream--<>
|
179
|
+
<>
|
180
|
+
EOF
|
181
|
+
mutipart.gsub!('<>',"\r")
|
182
|
+
inputs = {}
|
183
|
+
stream_input = :stream_input
|
184
|
+
inputs[:input1] = "Input1"
|
185
|
+
inputs[:input2] = "Input2"
|
186
|
+
num = 50
|
187
|
+
cpus = 1
|
188
|
+
Log.severity = 0
|
189
|
+
Misc.bootstrap((0..num-1).to_a, cpus) do |n|
|
190
|
+
puts mutipart
|
191
|
+
TmpFile.with_file(mutipart, false) do |tmpfile|
|
192
|
+
inputs = inputs.dup
|
193
|
+
inputs[:stream_input] = File.open(tmpfile)
|
194
|
+
|
195
|
+
puts "wget '#{URL}' --post-file #{ tmpfile } -O -"
|
196
|
+
io = CMD.cmd("wget '#{URL}' --post-file #{ tmpfile } -O -", :pipe => true)
|
197
|
+
assert_equal mutipart, io.read
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.20.
|
4
|
+
version: 5.20.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -432,6 +432,7 @@ files:
|
|
432
432
|
- test/rbbt/util/log/test_progress.rb
|
433
433
|
- test/rbbt/util/misc/test_bgzf.rb
|
434
434
|
- test/rbbt/util/misc/test_lock.rb
|
435
|
+
- test/rbbt/util/misc/test_multipart_payload.rb
|
435
436
|
- test/rbbt/util/misc/test_pipes.rb
|
436
437
|
- test/rbbt/util/simpleopt/test_get.rb
|
437
438
|
- test/rbbt/util/simpleopt/test_parse.rb
|
@@ -491,6 +492,7 @@ test_files:
|
|
491
492
|
- test/rbbt/util/test_log.rb
|
492
493
|
- test/rbbt/util/test_open.rb
|
493
494
|
- test/rbbt/util/misc/test_lock.rb
|
495
|
+
- test/rbbt/util/misc/test_multipart_payload.rb
|
494
496
|
- test/rbbt/util/misc/test_bgzf.rb
|
495
497
|
- test/rbbt/util/misc/test_pipes.rb
|
496
498
|
- test/rbbt/util/test_concurrency.rb
|