rflow 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/schema/message.avsc CHANGED
@@ -22,6 +22,12 @@
22
22
  }
23
23
  }
24
24
  },
25
+ {"name": "properties",
26
+ "type": {
27
+ "type": "map",
28
+ "values": "string"
29
+ }
30
+ },
25
31
  {"name": "data_serialization_type",
26
32
  "type": {
27
33
  "type": "enum",
@@ -33,4 +39,3 @@
33
39
  {"name": "data", "type": "bytes"}
34
40
  ]
35
41
  }
36
-
@@ -2,39 +2,39 @@ require 'spec_helper'
2
2
 
3
3
  class RFlow
4
4
  class Component
5
- context "Input and output ports" do
5
+ context 'Input and output ports' do
6
6
  let(:connection) { RFlow::Connection.new(RFlow::Configuration::NullConnectionConfiguration.new) }
7
7
  let(:message) { RFlow::Message.new('RFlow::Message::Data::Raw') }
8
8
 
9
9
  describe Port do
10
- it "should not be connected" do
10
+ it 'should not be connected' do
11
11
  expect(described_class.new(nil)).not_to be_connected
12
12
  end
13
13
  end
14
14
 
15
15
  describe HashPort do
16
- it "should not be connected" do
16
+ it 'should not be connected' do
17
17
  expect(described_class.new(nil)).not_to be_connected
18
18
  end
19
19
  end
20
20
 
21
21
  [InputPort, OutputPort].each do |c|
22
22
  describe c do
23
- context "#add_connection" do
24
- it "should add the connection" do
23
+ context '#add_connection' do
24
+ it 'should add the connection' do
25
25
  described_class.new(nil).tap do |port|
26
26
  port.add_connection(nil, connection)
27
- expect(port[nil]).to include connection
27
+ expect(port[nil].connections).to include connection
28
28
  end
29
29
  end
30
30
  end
31
31
 
32
- context "#remove_connection" do
33
- it "should remove the connection" do
32
+ context '#remove_connection' do
33
+ it 'should remove the connection' do
34
34
  described_class.new(nil).tap do |port|
35
35
  port.add_connection(nil, connection)
36
36
  port.remove_connection(nil, connection)
37
- expect(port[nil]).not_to include connection
37
+ expect(port[nil].connections).not_to include connection
38
38
  end
39
39
  end
40
40
  end
@@ -42,8 +42,8 @@ class RFlow
42
42
  end
43
43
 
44
44
  describe InputPort do
45
- context "#connect!" do
46
- it "should be connected" do
45
+ context '#connect!' do
46
+ it 'should be connected' do
47
47
  expect(connection).to receive(:connect_input!)
48
48
 
49
49
  described_class.new(nil).tap do |port|
@@ -57,8 +57,8 @@ class RFlow
57
57
  end
58
58
 
59
59
  describe OutputPort do
60
- context "#connect!" do
61
- it "should be connected" do
60
+ context '#connect!' do
61
+ it 'should be connected' do
62
62
  expect(connection).to receive(:connect_output!)
63
63
 
64
64
  described_class.new(nil).tap do |port|
@@ -70,8 +70,8 @@ class RFlow
70
70
  end
71
71
  end
72
72
 
73
- context "#add_connection" do
74
- it "should deliver messages to the new connection" do
73
+ context '#add_connection' do
74
+ it 'should deliver messages to the new connection' do
75
75
  described_class.new(nil).tap do |port|
76
76
  port.connect!
77
77
  port.all_connections # trigger caching
@@ -85,8 +85,8 @@ class RFlow
85
85
  end
86
86
  end
87
87
 
88
- context "#remove_connection" do
89
- it "should not deliver messages to the old connection" do
88
+ context '#remove_connection' do
89
+ it 'should not deliver messages to the old connection' do
90
90
  described_class.new(nil).tap do |port|
91
91
  allow(connection).to receive(:connect_output!)
92
92
  port.add_connection(nil, connection)
@@ -4,7 +4,7 @@ class RFlow
4
4
  module Components
5
5
  describe Clock do
6
6
  before(:each) do
7
- ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
7
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
8
8
  Configuration.migrate_database
9
9
  end
10
10
 
@@ -5,11 +5,11 @@ class RFlow
5
5
  class Configuration
6
6
  describe RubyDSL do
7
7
  before(:each) do
8
- ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
8
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
9
9
  Configuration.migrate_database
10
10
  end
11
11
 
12
- it "should correctly process an empty DSL" do
12
+ it 'should correctly process an empty DSL' do
13
13
  described_class.configure {}
14
14
 
15
15
  expect(Shard).to have(0).shards
@@ -18,7 +18,7 @@ class RFlow
18
18
  expect(Connection).to have(0).connections
19
19
  end
20
20
 
21
- it "should correctly process a component declaration" do
21
+ it 'should correctly process a component declaration' do
22
22
  described_class.configure do |c|
23
23
  c.component 'boom', 'town', 'opt1' => 'OPT1', 'opt2' => 'OPT2'
24
24
  end
@@ -35,7 +35,7 @@ class RFlow
35
35
  end
36
36
  end
37
37
 
38
- it "should correctly process a connect declaration" do
38
+ it 'should correctly process a connect declaration' do
39
39
  described_class.configure do |c|
40
40
  c.component 'first', 'First'
41
41
  c.component 'second', 'Second'
@@ -109,32 +109,32 @@ class RFlow
109
109
  end
110
110
  end
111
111
 
112
- it "should correctly process shard declarations" do
112
+ it 'should correctly process shard declarations' do
113
113
  described_class.configure do |c|
114
114
  c.component 'first', 'First', :opt1 => 'opt1'
115
115
 
116
- c.shard "s1", :process => 2 do |s|
117
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
116
+ c.shard 's1', :process => 2 do |s|
117
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
118
118
  end
119
119
 
120
- c.shard "s2", :type => :process, :count => 10 do |s|
120
+ c.shard 's2', :type => :process, :count => 10 do |s|
121
121
  s.component 'third', 'Third'
122
122
  s.component 'fourth', 'Fourth'
123
123
  end
124
124
 
125
- c.process "s3", :count => 10 do |s|
125
+ c.process 's3', :count => 10 do |s|
126
126
  s.component 'fifth', 'Fifth'
127
127
  end
128
128
 
129
- c.shard "s-ignored", :type => :process, :count => 10 do
129
+ c.shard 's-ignored', :type => :process, :count => 10 do
130
130
  # ignored because there are no components
131
131
  end
132
132
 
133
- c.thread "s4", :count => 10 do |s|
133
+ c.thread 's4', :count => 10 do |s|
134
134
  s.component 'sixth', 'Sixth'
135
135
  end
136
136
 
137
- c.shard "s5", :type => :thread, :count => 10 do |s|
137
+ c.shard 's5', :type => :thread, :count => 10 do |s|
138
138
  s.component 'seventh', 'Seventh'
139
139
  end
140
140
 
@@ -173,12 +173,12 @@ class RFlow
173
173
  'third#out=>sixth#in'])
174
174
  end
175
175
 
176
- it "should generate PUSH-PULL inproc ZeroMQ connections for in-shard connections" do
176
+ it 'should generate PUSH-PULL inproc ZeroMQ connections for in-shard connections' do
177
177
  described_class.configure do |c|
178
178
 
179
- c.shard "s1", :process => 2 do |s|
179
+ c.shard 's1', :process => 2 do |s|
180
180
  s.component 'first', 'First', :opt1 => 'opt1'
181
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
181
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
182
182
  end
183
183
 
184
184
  c.connect 'first#out' => 'second#in'
@@ -205,15 +205,15 @@ class RFlow
205
205
  end
206
206
  end
207
207
 
208
- it "should generate PUSH-PULL ipc ZeroMQ connections for one-to-one inter-shard connections" do
208
+ it 'should generate PUSH-PULL ipc ZeroMQ connections for one-to-one inter-shard connections' do
209
209
  described_class.configure do |c|
210
210
 
211
- c.shard "s1", :process => 1 do |s|
211
+ c.shard 's1', :process => 1 do |s|
212
212
  s.component 'first', 'First', :opt1 => 'opt1'
213
213
  end
214
214
 
215
- c.shard "s2", :process => 1 do |s|
216
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
215
+ c.shard 's2', :process => 1 do |s|
216
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
217
217
  end
218
218
 
219
219
  c.connect 'first#out' => 'second#in'
@@ -240,15 +240,15 @@ class RFlow
240
240
  end
241
241
  end
242
242
 
243
- it "should generate PUSH-PULL ipc ZeroMQ connections for one-to-many inter-shard connections" do
243
+ it 'should generate PUSH-PULL ipc ZeroMQ connections for one-to-many inter-shard connections' do
244
244
  described_class.configure do |c|
245
245
 
246
- c.shard "s1", :process => 1 do |s|
246
+ c.shard 's1', :process => 1 do |s|
247
247
  s.component 'first', 'First', :opt1 => 'opt1'
248
248
  end
249
249
 
250
- c.shard "s2", :process => 3 do |s|
251
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
250
+ c.shard 's2', :process => 3 do |s|
251
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
252
252
  end
253
253
 
254
254
  c.connect 'first#out' => 'second#in'
@@ -275,15 +275,15 @@ class RFlow
275
275
  end
276
276
  end
277
277
 
278
- it "should generate PUSH-PULL ipc ZeroMQ connections for many-to-one inter-shard connections" do
278
+ it 'should generate PUSH-PULL ipc ZeroMQ connections for many-to-one inter-shard connections' do
279
279
  described_class.configure do |c|
280
280
 
281
- c.shard "s1", :process => 3 do |s|
281
+ c.shard 's1', :process => 3 do |s|
282
282
  s.component 'first', 'First', :opt1 => 'opt1'
283
283
  end
284
284
 
285
- c.shard "s2", :process => 1 do |s|
286
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
285
+ c.shard 's2', :process => 1 do |s|
286
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
287
287
  end
288
288
 
289
289
  c.connect 'first#out' => 'second#in'
@@ -310,15 +310,15 @@ class RFlow
310
310
  end
311
311
  end
312
312
 
313
- it "should generate PUSH-PULL brokered ZeroMQ connections for many-to-many inter-shard connections" do
313
+ it 'should generate PUSH-PULL brokered ZeroMQ connections for many-to-many inter-shard connections' do
314
314
  described_class.configure do |c|
315
315
 
316
- c.shard "s1", :process => 3 do |s|
316
+ c.shard 's1', :process => 3 do |s|
317
317
  s.component 'first', 'First', :opt1 => 'opt1'
318
318
  end
319
319
 
320
- c.shard "s2", :process => 3 do |s|
321
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
320
+ c.shard 's2', :process => 3 do |s|
321
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
322
322
  end
323
323
 
324
324
  c.connect 'first#out' => 'second#in'
@@ -345,15 +345,15 @@ class RFlow
345
345
  end
346
346
  end
347
347
 
348
- it "should generate PUB-SUB ipc ZeroMQ connections for one-to-many broadcast connections" do
348
+ it 'should generate PUB-SUB ipc ZeroMQ connections for one-to-many broadcast connections' do
349
349
  described_class.configure do |c|
350
350
 
351
- c.shard "s1", :process => 1 do |s|
351
+ c.shard 's1', :process => 1 do |s|
352
352
  s.component 'first', 'First', :opt1 => 'opt1'
353
353
  end
354
354
 
355
- c.shard "s2", :process => 3 do |s|
356
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
355
+ c.shard 's2', :process => 3 do |s|
356
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
357
357
  end
358
358
 
359
359
  c.connect 'first#out' => 'second#in', :delivery => 'broadcast'
@@ -380,15 +380,15 @@ class RFlow
380
380
  end
381
381
  end
382
382
 
383
- it "should generate PUB-SUB brokered ZeroMQ connections for many-to-many broadcast connections" do
383
+ it 'should generate PUB-SUB brokered ZeroMQ connections for many-to-many broadcast connections' do
384
384
  described_class.configure do |c|
385
385
 
386
- c.shard "s1", :process => 3 do |s|
386
+ c.shard 's1', :process => 3 do |s|
387
387
  s.component 'first', 'First', :opt1 => 'opt1'
388
388
  end
389
389
 
390
- c.shard "s2", :process => 3 do |s|
391
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
390
+ c.shard 's2', :process => 3 do |s|
391
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
392
392
  end
393
393
 
394
394
  c.connect 'first#out' => 'second#in', :delivery => 'broadcast'
@@ -415,12 +415,12 @@ class RFlow
415
415
  end
416
416
  end
417
417
 
418
- it "should generate PUB-SUB brokered ZeroMQ connections for many-to-many in-shard broadcast connections" do
418
+ it 'should generate PUB-SUB brokered ZeroMQ connections for many-to-many in-shard broadcast connections' do
419
419
  described_class.configure do |c|
420
420
 
421
- c.shard "s1", :process => 3 do |s|
421
+ c.shard 's1', :process => 3 do |s|
422
422
  s.component 'first', 'First', :opt1 => 'opt1'
423
- s.component 'second', 'Second', :opt1 => 'opt1', "opt2" => "opt2"
423
+ s.component 'second', 'Second', :opt1 => 'opt1', 'opt2' => 'opt2'
424
424
  end
425
425
 
426
426
  c.connect 'first#out' => 'second#in', :delivery => 'broadcast'
@@ -447,7 +447,7 @@ class RFlow
447
447
  end
448
448
  end
449
449
 
450
- it "should not allow two components with the same name" do
450
+ it 'should not allow two components with the same name' do
451
451
  expect {
452
452
  described_class.configure do |c|
453
453
  c.component 'first', 'First'
@@ -456,13 +456,13 @@ class RFlow
456
456
  }.to raise_error(ActiveRecord::RecordInvalid)
457
457
  end
458
458
 
459
- it "should not allow two shards with the same name" do
459
+ it 'should not allow two shards with the same name' do
460
460
  expect {
461
461
  described_class.configure do |c|
462
- c.shard("s1", :process => 2) {|c| c.component 'x', 'y' }
463
- c.shard("s1", :process => 2) {|c| c.component 'z', 'q' }
462
+ c.shard('s1', :process => 2) {|c| c.component 'x', 'y' }
463
+ c.shard('s1', :process => 2) {|c| c.component 'z', 'q' }
464
464
  end
465
- }.to raise_error
465
+ }.to raise_error(ActiveRecord::RecordInvalid)
466
466
  end
467
467
  end
468
468
  end
@@ -5,12 +5,12 @@ class RFlow
5
5
  describe Configuration do
6
6
  describe '.add_available_data_type' do
7
7
  context 'if passed a data_serialization that is not avro' do
8
- it "should throw an exception" do
8
+ it 'should throw an exception' do
9
9
  expect { Configuration.add_available_data_type('A', 'boom', 'schema') }.to raise_error(
10
10
  ArgumentError, "Data serialization_type must be 'avro' for 'A'")
11
11
  end
12
12
 
13
- it "should not update the available_data_types" do
13
+ it 'should not update the available_data_types' do
14
14
  expect {
15
15
  Configuration.add_available_data_type('A', 'boom', 'schema') rescue nil
16
16
  }.not_to change { Configuration.available_data_types.size }
@@ -18,18 +18,18 @@ class RFlow
18
18
  end
19
19
  end
20
20
 
21
- describe "Data Extensions" do
22
- describe ".add_available_data_extension" do
21
+ describe 'Data Extensions' do
22
+ describe '.add_available_data_extension' do
23
23
  context 'if passed a non-module data extension' do
24
- it "should throw an exception" do
24
+ it 'should throw an exception' do
25
25
  expect {
26
26
  Configuration.add_available_data_extension('data_type', 'NOTAMODULE')
27
- }.to raise_error(ArgumentError, "Invalid data extension NOTAMODULE for data_type. Only Ruby Modules allowed")
27
+ }.to raise_error(ArgumentError, 'Invalid data extension NOTAMODULE for data_type. Only Ruby Modules allowed')
28
28
  end
29
29
  end
30
30
 
31
- context "if passed a valid Module as a data extension" do
32
- it "should update the available_data_extensions" do
31
+ context 'if passed a valid Module as a data extension' do
32
+ it 'should update the available_data_extensions' do
33
33
  expect {
34
34
  Configuration.add_available_data_extension('data_type', Module.new)
35
35
  }.to change { Configuration.available_data_extensions['data_type'].size }.by(1)
@@ -3,38 +3,67 @@ require 'spec_helper'
3
3
  class RFlow
4
4
  describe ForwardToInputPort do
5
5
  before(:each) do
6
- ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
6
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
7
7
  Configuration.migrate_database
8
8
  end
9
9
 
10
- let(:filtered_messages) { [] }
10
+ let(:accepted_messages) { [] }
11
11
  let(:dropped_messages) { [] }
12
12
 
13
13
  let(:generator) do
14
14
  RFlow::Components::GenerateIntegerSequence.new.tap do |c|
15
15
  c.configure!({})
16
- c.out.direct_connect ruby_proc_filter.in
17
16
  end
18
17
  end
19
18
 
20
- let(:ruby_proc_filter) do
19
+ let(:accept_evens) do
21
20
  RFlow::Components::RubyProcFilter.new.tap do |c|
22
21
  c.configure! 'filter_proc_string' => 'message.data.data_object % 2 == 0'
23
22
  end
24
23
  end
25
24
 
26
25
  it 'should forward generated integers to be filtered by the proc filter' do
27
- ruby_proc_filter.filtered.collect_messages(nil, filtered_messages) do
28
- ruby_proc_filter.dropped.collect_messages(nil, dropped_messages) do
26
+ generator.out.direct_connect accept_evens.in
27
+
28
+ accept_evens.filtered.collect_messages(nil, accepted_messages) do
29
+ accept_evens.dropped.collect_messages(nil, dropped_messages) do
30
+ 5.times { generator.generate }
31
+ end
32
+ end
33
+
34
+ expect(accepted_messages).to have(3).messages
35
+ expect(accepted_messages.map(&:data).map(&:data_object)).to eq([0, 2, 4])
36
+ expect(dropped_messages).to have(2).messages
37
+ expect(dropped_messages.map(&:data).map(&:data_object)).to eq([1, 3])
38
+ end
39
+
40
+ it 'should forward integers from the union of subports' do
41
+ generator.even_odd_out.direct_connect accept_evens.in
42
+
43
+ accept_evens.filtered.collect_messages(nil, accepted_messages) do
44
+ accept_evens.dropped.collect_messages(nil, dropped_messages) do
29
45
  5.times { generator.generate }
30
46
  end
31
47
  end
32
48
 
33
- expect(filtered_messages).to have(3).messages
34
- expect(filtered_messages.map(&:data).map(&:data_object)).to eq([0, 2, 4])
49
+ expect(accepted_messages).to have(3).messages
50
+ expect(accepted_messages.map(&:data).map(&:data_object)).to eq([0, 2, 4])
35
51
  expect(dropped_messages).to have(2).messages
36
52
  expect(dropped_messages.map(&:data).map(&:data_object)).to eq([1, 3])
37
53
  end
54
+
55
+ it 'should forward integers from a subport' do
56
+ generator.even_odd_out['even'].direct_connect accept_evens.in
57
+
58
+ accept_evens.filtered.collect_messages(nil, accepted_messages) do
59
+ accept_evens.dropped.collect_messages(nil, dropped_messages) do
60
+ 5.times { generator.generate }
61
+ end
62
+ end
63
+
64
+ expect(accepted_messages).to have(3).messages
65
+ expect(accepted_messages.map(&:data).map(&:data_object)).to eq([0, 2, 4])
66
+ expect(dropped_messages).to have(0).messages
67
+ end
38
68
  end
39
69
  end
40
-