rflow 1.0.1 → 1.1.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.
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
-