deimos-temp-fork 0.0.1
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 +7 -0
- data/.circleci/config.yml +83 -0
- data/.gitignore +41 -0
- data/.gitmodules +0 -0
- data/.rspec +1 -0
- data/.rubocop.yml +333 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +349 -0
- data/CODE_OF_CONDUCT.md +77 -0
- data/Dockerfile +23 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +286 -0
- data/Guardfile +22 -0
- data/LICENSE.md +195 -0
- data/README.md +1099 -0
- data/Rakefile +13 -0
- data/bin/deimos +4 -0
- data/deimos-ruby.gemspec +44 -0
- data/docker-compose.yml +71 -0
- data/docs/ARCHITECTURE.md +140 -0
- data/docs/CONFIGURATION.md +236 -0
- data/docs/DATABASE_BACKEND.md +147 -0
- data/docs/INTEGRATION_TESTS.md +52 -0
- data/docs/PULL_REQUEST_TEMPLATE.md +35 -0
- data/docs/UPGRADING.md +128 -0
- data/lib/deimos-temp-fork.rb +95 -0
- data/lib/deimos/active_record_consume/batch_consumption.rb +164 -0
- data/lib/deimos/active_record_consume/batch_slicer.rb +27 -0
- data/lib/deimos/active_record_consume/message_consumption.rb +79 -0
- data/lib/deimos/active_record_consume/schema_model_converter.rb +52 -0
- data/lib/deimos/active_record_consumer.rb +67 -0
- data/lib/deimos/active_record_producer.rb +87 -0
- data/lib/deimos/backends/base.rb +32 -0
- data/lib/deimos/backends/db.rb +41 -0
- data/lib/deimos/backends/kafka.rb +33 -0
- data/lib/deimos/backends/kafka_async.rb +33 -0
- data/lib/deimos/backends/test.rb +20 -0
- data/lib/deimos/batch_consumer.rb +7 -0
- data/lib/deimos/config/configuration.rb +381 -0
- data/lib/deimos/config/phobos_config.rb +137 -0
- data/lib/deimos/consume/batch_consumption.rb +150 -0
- data/lib/deimos/consume/message_consumption.rb +94 -0
- data/lib/deimos/consumer.rb +104 -0
- data/lib/deimos/instrumentation.rb +76 -0
- data/lib/deimos/kafka_message.rb +60 -0
- data/lib/deimos/kafka_source.rb +128 -0
- data/lib/deimos/kafka_topic_info.rb +102 -0
- data/lib/deimos/message.rb +79 -0
- data/lib/deimos/metrics/datadog.rb +47 -0
- data/lib/deimos/metrics/mock.rb +39 -0
- data/lib/deimos/metrics/provider.rb +36 -0
- data/lib/deimos/monkey_patches/phobos_cli.rb +35 -0
- data/lib/deimos/monkey_patches/phobos_producer.rb +51 -0
- data/lib/deimos/poll_info.rb +9 -0
- data/lib/deimos/producer.rb +224 -0
- data/lib/deimos/railtie.rb +8 -0
- data/lib/deimos/schema_backends/avro_base.rb +140 -0
- data/lib/deimos/schema_backends/avro_local.rb +30 -0
- data/lib/deimos/schema_backends/avro_schema_coercer.rb +119 -0
- data/lib/deimos/schema_backends/avro_schema_registry.rb +34 -0
- data/lib/deimos/schema_backends/avro_validation.rb +21 -0
- data/lib/deimos/schema_backends/base.rb +150 -0
- data/lib/deimos/schema_backends/mock.rb +42 -0
- data/lib/deimos/shared_config.rb +63 -0
- data/lib/deimos/test_helpers.rb +360 -0
- data/lib/deimos/tracing/datadog.rb +35 -0
- data/lib/deimos/tracing/mock.rb +40 -0
- data/lib/deimos/tracing/provider.rb +29 -0
- data/lib/deimos/utils/db_poller.rb +150 -0
- data/lib/deimos/utils/db_producer.rb +243 -0
- data/lib/deimos/utils/deadlock_retry.rb +68 -0
- data/lib/deimos/utils/inline_consumer.rb +150 -0
- data/lib/deimos/utils/lag_reporter.rb +175 -0
- data/lib/deimos/utils/schema_controller_mixin.rb +115 -0
- data/lib/deimos/version.rb +5 -0
- data/lib/generators/deimos/active_record/templates/migration.rb.tt +28 -0
- data/lib/generators/deimos/active_record/templates/model.rb.tt +5 -0
- data/lib/generators/deimos/active_record_generator.rb +79 -0
- data/lib/generators/deimos/db_backend/templates/migration +25 -0
- data/lib/generators/deimos/db_backend/templates/rails3_migration +31 -0
- data/lib/generators/deimos/db_backend_generator.rb +48 -0
- data/lib/generators/deimos/db_poller/templates/migration +11 -0
- data/lib/generators/deimos/db_poller/templates/rails3_migration +16 -0
- data/lib/generators/deimos/db_poller_generator.rb +48 -0
- data/lib/tasks/deimos.rake +34 -0
- data/spec/active_record_batch_consumer_spec.rb +481 -0
- data/spec/active_record_consume/batch_slicer_spec.rb +42 -0
- data/spec/active_record_consume/schema_model_converter_spec.rb +105 -0
- data/spec/active_record_consumer_spec.rb +154 -0
- data/spec/active_record_producer_spec.rb +85 -0
- data/spec/backends/base_spec.rb +10 -0
- data/spec/backends/db_spec.rb +54 -0
- data/spec/backends/kafka_async_spec.rb +11 -0
- data/spec/backends/kafka_spec.rb +11 -0
- data/spec/batch_consumer_spec.rb +256 -0
- data/spec/config/configuration_spec.rb +248 -0
- data/spec/consumer_spec.rb +209 -0
- data/spec/deimos_spec.rb +169 -0
- data/spec/generators/active_record_generator_spec.rb +56 -0
- data/spec/handlers/my_batch_consumer.rb +10 -0
- data/spec/handlers/my_consumer.rb +10 -0
- data/spec/kafka_listener_spec.rb +55 -0
- data/spec/kafka_source_spec.rb +381 -0
- data/spec/kafka_topic_info_spec.rb +111 -0
- data/spec/message_spec.rb +19 -0
- data/spec/phobos.bad_db.yml +73 -0
- data/spec/phobos.yml +77 -0
- data/spec/producer_spec.rb +498 -0
- data/spec/rake_spec.rb +19 -0
- data/spec/schema_backends/avro_base_shared.rb +199 -0
- data/spec/schema_backends/avro_local_spec.rb +32 -0
- data/spec/schema_backends/avro_schema_registry_spec.rb +32 -0
- data/spec/schema_backends/avro_validation_spec.rb +24 -0
- data/spec/schema_backends/base_spec.rb +33 -0
- data/spec/schemas/com/my-namespace/Generated.avsc +71 -0
- data/spec/schemas/com/my-namespace/MyNestedSchema.avsc +62 -0
- data/spec/schemas/com/my-namespace/MySchema-key.avsc +13 -0
- data/spec/schemas/com/my-namespace/MySchema.avsc +18 -0
- data/spec/schemas/com/my-namespace/MySchemaCompound-key.avsc +18 -0
- data/spec/schemas/com/my-namespace/MySchemaWithBooleans.avsc +18 -0
- data/spec/schemas/com/my-namespace/MySchemaWithDateTimes.avsc +33 -0
- data/spec/schemas/com/my-namespace/MySchemaWithId.avsc +28 -0
- data/spec/schemas/com/my-namespace/MySchemaWithUniqueId.avsc +32 -0
- data/spec/schemas/com/my-namespace/Wibble.avsc +43 -0
- data/spec/schemas/com/my-namespace/Widget.avsc +27 -0
- data/spec/schemas/com/my-namespace/WidgetTheSecond.avsc +27 -0
- data/spec/schemas/com/my-namespace/request/CreateTopic.avsc +11 -0
- data/spec/schemas/com/my-namespace/request/Index.avsc +11 -0
- data/spec/schemas/com/my-namespace/request/UpdateRequest.avsc +11 -0
- data/spec/schemas/com/my-namespace/response/CreateTopic.avsc +11 -0
- data/spec/schemas/com/my-namespace/response/Index.avsc +11 -0
- data/spec/schemas/com/my-namespace/response/UpdateResponse.avsc +11 -0
- data/spec/spec_helper.rb +267 -0
- data/spec/utils/db_poller_spec.rb +320 -0
- data/spec/utils/db_producer_spec.rb +514 -0
- data/spec/utils/deadlock_retry_spec.rb +74 -0
- data/spec/utils/inline_consumer_spec.rb +31 -0
- data/spec/utils/lag_reporter_spec.rb +76 -0
- data/spec/utils/platform_schema_validation_spec.rb +0 -0
- data/spec/utils/schema_controller_mixin_spec.rb +84 -0
- data/support/deimos-solo.png +0 -0
- data/support/deimos-with-name-next.png +0 -0
- data/support/deimos-with-name.png +0 -0
- data/support/flipp-logo.png +0 -0
- metadata +551 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# :nodoc:
|
|
4
|
+
module ConsumerTest
|
|
5
|
+
describe Deimos::Consumer, 'Message Consumer' do
|
|
6
|
+
|
|
7
|
+
prepend_before(:each) do
|
|
8
|
+
# :nodoc:
|
|
9
|
+
consumer_class = Class.new(described_class) do
|
|
10
|
+
schema 'MySchema'
|
|
11
|
+
namespace 'com.my-namespace'
|
|
12
|
+
key_config field: 'test_id'
|
|
13
|
+
|
|
14
|
+
# :nodoc:
|
|
15
|
+
def fatal_error?(_exception, payload, _metadata)
|
|
16
|
+
payload == 'fatal'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# :nodoc:
|
|
20
|
+
def consume(_payload, _metadata)
|
|
21
|
+
raise 'This should not be called unless call_original is set'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
stub_const('ConsumerTest::MyConsumer', consumer_class)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should consume a message' do
|
|
28
|
+
test_consume_message(MyConsumer,
|
|
29
|
+
'test_id' => 'foo',
|
|
30
|
+
'some_int' => 123) do |payload, _metadata|
|
|
31
|
+
expect(payload['test_id']).to eq('foo')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'should consume a nil message' do
|
|
36
|
+
test_consume_message(MyConsumer, nil) do |payload, _metadata|
|
|
37
|
+
expect(payload).to be_nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'should consume a message idempotently' do
|
|
42
|
+
# testing for a crash and re-consuming the same message/metadata
|
|
43
|
+
key = { 'test_id' => 'foo' }
|
|
44
|
+
test_metadata = { key: key }
|
|
45
|
+
allow_any_instance_of(MyConsumer).to(receive(:decode_key)) do |_instance, k|
|
|
46
|
+
k['test_id']
|
|
47
|
+
end
|
|
48
|
+
MyConsumer.new.around_consume({ 'test_id' => 'foo',
|
|
49
|
+
'some_int' => 123 }, test_metadata) do |_payload, metadata|
|
|
50
|
+
expect(metadata[:key]).to eq('foo')
|
|
51
|
+
end
|
|
52
|
+
MyConsumer.new.around_consume({ 'test_id' => 'foo',
|
|
53
|
+
'some_int' => 123 }, test_metadata) do |_payload, metadata|
|
|
54
|
+
expect(metadata[:key]).to eq('foo')
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'should consume a message on a topic' do
|
|
59
|
+
test_consume_message('my_consume_topic',
|
|
60
|
+
'test_id' => 'foo',
|
|
61
|
+
'some_int' => 123) do |payload, _metadata|
|
|
62
|
+
expect(payload['test_id']).to eq('foo')
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should fail on invalid message' do
|
|
67
|
+
test_consume_invalid_message(MyConsumer, 'invalid' => 'key')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'should fail if reraise is false but fatal_error is true' do
|
|
71
|
+
Deimos.configure { |config| config.consumers.reraise_errors = false }
|
|
72
|
+
test_consume_invalid_message(MyConsumer, 'fatal')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'should fail if fatal_error is true globally' do
|
|
76
|
+
Deimos.configure do |config|
|
|
77
|
+
config.consumers.fatal_error = proc { true }
|
|
78
|
+
config.consumers.reraise_errors = false
|
|
79
|
+
end
|
|
80
|
+
test_consume_invalid_message(MyConsumer, 'invalid' => 'key')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'should fail on message with extra fields' do
|
|
84
|
+
test_consume_invalid_message(MyConsumer,
|
|
85
|
+
'test_id' => 'foo',
|
|
86
|
+
'some_int' => 123,
|
|
87
|
+
'extra_field' => 'field name')
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'should not fail when before_consume fails without reraising errors' do
|
|
91
|
+
Deimos.configure { |config| config.consumers.reraise_errors = false }
|
|
92
|
+
expect {
|
|
93
|
+
test_consume_message(
|
|
94
|
+
MyConsumer,
|
|
95
|
+
{ 'test_id' => 'foo',
|
|
96
|
+
'some_int' => 123 },
|
|
97
|
+
{ skip_expectation: true }
|
|
98
|
+
) { raise 'OH NOES' }
|
|
99
|
+
}.not_to raise_error
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'should not fail when consume fails without reraising errors' do
|
|
103
|
+
Deimos.configure { |config| config.consumers.reraise_errors = false }
|
|
104
|
+
expect {
|
|
105
|
+
test_consume_message(
|
|
106
|
+
MyConsumer,
|
|
107
|
+
{ 'invalid' => 'key' },
|
|
108
|
+
{ skip_expectation: true }
|
|
109
|
+
)
|
|
110
|
+
}.not_to raise_error
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'should call original' do
|
|
114
|
+
expect {
|
|
115
|
+
test_consume_message(MyConsumer,
|
|
116
|
+
{ 'test_id' => 'foo', 'some_int' => 123 },
|
|
117
|
+
{ call_original: true })
|
|
118
|
+
}.to raise_error('This should not be called unless call_original is set')
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe 'decode_key' do
|
|
122
|
+
|
|
123
|
+
it 'should use the key field in the value if set' do
|
|
124
|
+
# actual decoding is disabled in test
|
|
125
|
+
expect(MyConsumer.new.decode_key('test_id' => '123')).to eq('123')
|
|
126
|
+
expect { MyConsumer.new.decode_key(123) }.to raise_error(NoMethodError)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'should use the key schema if set' do
|
|
130
|
+
consumer_class = Class.new(described_class) do
|
|
131
|
+
schema 'MySchema'
|
|
132
|
+
namespace 'com.my-namespace'
|
|
133
|
+
key_config schema: 'MySchema_key'
|
|
134
|
+
end
|
|
135
|
+
stub_const('ConsumerTest::MySchemaConsumer', consumer_class)
|
|
136
|
+
expect(MyConsumer.new.decode_key('test_id' => '123')).to eq('123')
|
|
137
|
+
expect { MyConsumer.new.decode_key(123) }.to raise_error(NoMethodError)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'should not decode if plain is set' do
|
|
141
|
+
consumer_class = Class.new(described_class) do
|
|
142
|
+
schema 'MySchema'
|
|
143
|
+
namespace 'com.my-namespace'
|
|
144
|
+
key_config plain: true
|
|
145
|
+
end
|
|
146
|
+
stub_const('ConsumerTest::MyNonEncodedConsumer', consumer_class)
|
|
147
|
+
expect(MyNonEncodedConsumer.new.decode_key('123')).to eq('123')
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'should error with nothing set' do
|
|
151
|
+
consumer_class = Class.new(described_class) do
|
|
152
|
+
schema 'MySchema'
|
|
153
|
+
namespace 'com.my-namespace'
|
|
154
|
+
end
|
|
155
|
+
stub_const('ConsumerTest::MyErrorConsumer', consumer_class)
|
|
156
|
+
expect { MyErrorConsumer.new.decode_key('123') }.
|
|
157
|
+
to raise_error('No key config given - if you are not decoding keys, please use `key_config plain: true`')
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
describe 'timestamps' do
|
|
163
|
+
before(:each) do
|
|
164
|
+
# :nodoc:
|
|
165
|
+
consumer_class = Class.new(described_class) do
|
|
166
|
+
schema 'MySchemaWithDateTimes'
|
|
167
|
+
namespace 'com.my-namespace'
|
|
168
|
+
key_config plain: true
|
|
169
|
+
|
|
170
|
+
# :nodoc:
|
|
171
|
+
def consume(_payload, _metadata)
|
|
172
|
+
raise 'This should not be called unless call_original is set'
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
stub_const('ConsumerTest::MyConsumer', consumer_class)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'should consume a message' do
|
|
179
|
+
expect(Deimos.config.metrics).to receive(:histogram).twice
|
|
180
|
+
test_consume_message('my_consume_topic',
|
|
181
|
+
'test_id' => 'foo',
|
|
182
|
+
'some_int' => 123,
|
|
183
|
+
'updated_at' => Time.now.to_i,
|
|
184
|
+
'timestamp' => 2.minutes.ago.to_s) do |payload, _metadata|
|
|
185
|
+
expect(payload['test_id']).to eq('foo')
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it 'should fail nicely when timestamp wrong format' do
|
|
190
|
+
expect(Deimos.config.metrics).to receive(:histogram).twice
|
|
191
|
+
test_consume_message('my_consume_topic',
|
|
192
|
+
'test_id' => 'foo',
|
|
193
|
+
'some_int' => 123,
|
|
194
|
+
'updated_at' => Time.now.to_i,
|
|
195
|
+
'timestamp' => 'dffdf') do |payload, _metadata|
|
|
196
|
+
expect(payload['test_id']).to eq('foo')
|
|
197
|
+
end
|
|
198
|
+
test_consume_message('my_consume_topic',
|
|
199
|
+
'test_id' => 'foo',
|
|
200
|
+
'some_int' => 123,
|
|
201
|
+
'updated_at' => Time.now.to_i,
|
|
202
|
+
'timestamp' => '') do |payload, _metadata|
|
|
203
|
+
expect(payload['test_id']).to eq('foo')
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
data/spec/deimos_spec.rb
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe Deimos do
|
|
4
|
+
|
|
5
|
+
let(:phobos_configuration) do
|
|
6
|
+
{ 'logger' =>
|
|
7
|
+
{ 'file' => 'log/phobos.log',
|
|
8
|
+
'stdout_json' => false,
|
|
9
|
+
'level' => 'debug',
|
|
10
|
+
'ruby_kafka' =>
|
|
11
|
+
{ 'level' => 'debug' } },
|
|
12
|
+
'kafka' =>
|
|
13
|
+
{ 'client_id' => 'phobos',
|
|
14
|
+
'connect_timeout' => 15,
|
|
15
|
+
'socket_timeout' => 15,
|
|
16
|
+
'seed_brokers' => 'my_seed_broker.com',
|
|
17
|
+
'ssl_ca_cert' => 'my_ssl_ca_cert',
|
|
18
|
+
'ssl_client_cert' => 'my_ssl_client_cert',
|
|
19
|
+
'ssl_client_cert_key' => 'my_ssl_client_cert_key' },
|
|
20
|
+
'producer' =>
|
|
21
|
+
{ 'ack_timeout' => 5,
|
|
22
|
+
'required_acks' => :all,
|
|
23
|
+
'max_retries' => 2,
|
|
24
|
+
'retry_backoff' => 1,
|
|
25
|
+
'max_buffer_size' => 10_000,
|
|
26
|
+
'max_buffer_bytesize' => 10_000_000,
|
|
27
|
+
'compression_codec' => nil,
|
|
28
|
+
'compression_threshold' => 1,
|
|
29
|
+
'max_queue_size' => 10_000,
|
|
30
|
+
'delivery_threshold' => 0,
|
|
31
|
+
'delivery_interval' => 0 },
|
|
32
|
+
'consumer' =>
|
|
33
|
+
{ 'session_timeout' => 300,
|
|
34
|
+
'offset_commit_interval' => 10,
|
|
35
|
+
'offset_commit_threshold' => 0,
|
|
36
|
+
'heartbeat_interval' => 10 },
|
|
37
|
+
'backoff' =>
|
|
38
|
+
{ 'min_ms' => 1000,
|
|
39
|
+
'max_ms' => 60_000 },
|
|
40
|
+
'listeners' => [
|
|
41
|
+
{ 'handler' => 'ConsumerTest::MyConsumer',
|
|
42
|
+
'topic' => 'my_consume_topic',
|
|
43
|
+
'group_id' => 'my_group_id',
|
|
44
|
+
'max_bytes_per_partition' => 524_288 },
|
|
45
|
+
{ 'handler' => 'ConsumerTest::MyBatchConsumer',
|
|
46
|
+
'topic' => 'my_batch_consume_topic',
|
|
47
|
+
'group_id' => 'my_batch_group_id',
|
|
48
|
+
'delivery' => 'inline_batch' }
|
|
49
|
+
],
|
|
50
|
+
'custom_logger' => nil,
|
|
51
|
+
'custom_kafka_logger' => nil }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
let(:config_path) { File.join(File.dirname(__FILE__), 'phobos.yml') }
|
|
55
|
+
|
|
56
|
+
it 'should have a version number' do
|
|
57
|
+
expect(Deimos::VERSION).not_to be_nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'should error if required_acks is not all' do
|
|
61
|
+
expect {
|
|
62
|
+
described_class.configure do |config|
|
|
63
|
+
config.producers.backend = :db
|
|
64
|
+
config.phobos_config_file = File.join(File.dirname(__FILE__), 'phobos.bad_db.yml')
|
|
65
|
+
end
|
|
66
|
+
}.to raise_error('Cannot set producers.backend to :db unless producers.required_acks is set to ":all"!')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe '#start_db_backend!' do
|
|
70
|
+
it 'should start if backend is db and thread_count is > 0' do
|
|
71
|
+
signal_handler = instance_double(Sigurd::SignalHandler)
|
|
72
|
+
allow(signal_handler).to receive(:run!)
|
|
73
|
+
expect(Sigurd::Executor).to receive(:new).
|
|
74
|
+
with(anything, sleep_seconds: 5, logger: anything).and_call_original
|
|
75
|
+
expect(Sigurd::SignalHandler).to receive(:new) do |executor|
|
|
76
|
+
expect(executor.runners.size).to eq(2)
|
|
77
|
+
signal_handler
|
|
78
|
+
end
|
|
79
|
+
described_class.configure do |config|
|
|
80
|
+
config.producers.backend = :db
|
|
81
|
+
end
|
|
82
|
+
described_class.start_db_backend!(thread_count: 2)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'should not start if backend is not db' do
|
|
86
|
+
expect(Sigurd::SignalHandler).not_to receive(:new)
|
|
87
|
+
described_class.configure do |config|
|
|
88
|
+
config.producers.backend = :kafka
|
|
89
|
+
end
|
|
90
|
+
expect { described_class.start_db_backend!(thread_count: 2) }.
|
|
91
|
+
to raise_error('Publish backend is not set to :db, exiting')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should not start if thread_count is nil' do
|
|
95
|
+
expect(Sigurd::SignalHandler).not_to receive(:new)
|
|
96
|
+
described_class.configure do |config|
|
|
97
|
+
config.producers.backend = :db
|
|
98
|
+
end
|
|
99
|
+
expect { described_class.start_db_backend!(thread_count: nil) }.
|
|
100
|
+
to raise_error('Thread count is not given or set to zero, exiting')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'should not start if thread_count is 0' do
|
|
104
|
+
expect(Sigurd::SignalHandler).not_to receive(:new)
|
|
105
|
+
described_class.configure do |config|
|
|
106
|
+
config.producers.backend = :db
|
|
107
|
+
end
|
|
108
|
+
expect { described_class.start_db_backend!(thread_count: 0) }.
|
|
109
|
+
to raise_error('Thread count is not given or set to zero, exiting')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
describe 'delivery configuration' do
|
|
114
|
+
before(:each) do
|
|
115
|
+
allow(YAML).to receive(:load).and_return(phobos_configuration)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'should not raise an error with properly configured handlers' do
|
|
119
|
+
expect {
|
|
120
|
+
described_class.configure do
|
|
121
|
+
consumer do
|
|
122
|
+
class_name 'ConsumerTest::MyConsumer'
|
|
123
|
+
delivery :message
|
|
124
|
+
end
|
|
125
|
+
consumer do
|
|
126
|
+
class_name 'ConsumerTest::MyConsumer'
|
|
127
|
+
delivery :batch
|
|
128
|
+
end
|
|
129
|
+
consumer do
|
|
130
|
+
class_name 'ConsumerTest::MyBatchConsumer'
|
|
131
|
+
delivery :inline_batch
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
}.not_to raise_error
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'should raise an error if inline_batch listeners do not implement consume_batch' do
|
|
138
|
+
expect {
|
|
139
|
+
described_class.configure do
|
|
140
|
+
consumer do
|
|
141
|
+
class_name 'ConsumerTest::MyConsumer'
|
|
142
|
+
delivery :inline_batch
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
}.to raise_error('BatchConsumer ConsumerTest::MyConsumer does not implement `consume_batch`')
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'should raise an error if Consumers do not have message or batch delivery' do
|
|
149
|
+
expect {
|
|
150
|
+
described_class.configure do
|
|
151
|
+
consumer do
|
|
152
|
+
class_name 'ConsumerTest::MyBatchConsumer'
|
|
153
|
+
delivery :message
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
}.to raise_error('Non-batch Consumer ConsumerTest::MyBatchConsumer does not implement `consume`')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'should treat nil as `batch`' do
|
|
160
|
+
expect {
|
|
161
|
+
described_class.configure do
|
|
162
|
+
consumer do
|
|
163
|
+
class_name 'ConsumerTest::MyConsumer'
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
}.not_to raise_error
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'generators/deimos/active_record_generator'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Deimos::Generators::ActiveRecordGenerator do
|
|
6
|
+
|
|
7
|
+
after(:each) do
|
|
8
|
+
FileUtils.rm_rf('db') if File.exist?('db')
|
|
9
|
+
FileUtils.rm_rf('app') if File.exist?('app')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'should generate a migration' do
|
|
13
|
+
expect(Dir['db/migrate/*.rb']).to be_empty
|
|
14
|
+
expect(Dir['app/models/*.rb']).to be_empty
|
|
15
|
+
described_class.start(['generated_table', 'com.my-namespace.Generated'])
|
|
16
|
+
files = Dir['db/migrate/*.rb']
|
|
17
|
+
expect(files.length).to eq(1)
|
|
18
|
+
results = <<~MIGRATION
|
|
19
|
+
class CreateGeneratedTable < ActiveRecord::Migration[6.1]
|
|
20
|
+
def up
|
|
21
|
+
if table_exists?(:generated_table)
|
|
22
|
+
warn "generated_table already exists, exiting"
|
|
23
|
+
return
|
|
24
|
+
end
|
|
25
|
+
create_table :generated_table do |t|
|
|
26
|
+
t.string :a_string
|
|
27
|
+
t.integer :a_int
|
|
28
|
+
t.bigint :a_long
|
|
29
|
+
t.float :a_float
|
|
30
|
+
t.float :a_double
|
|
31
|
+
t.string :an_enum
|
|
32
|
+
t.json :an_array
|
|
33
|
+
t.json :a_map
|
|
34
|
+
t.json :a_record
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# TODO add indexes as necessary
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def down
|
|
41
|
+
return unless table_exists?(:generated_table)
|
|
42
|
+
drop_table :generated_table
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
MIGRATION
|
|
47
|
+
expect(File.read(files[0])).to eq(results)
|
|
48
|
+
model = <<~MODEL
|
|
49
|
+
class GeneratedTable < ApplicationRecord
|
|
50
|
+
enum an_enum: {sym1: 'sym1', sym2: 'sym2'}
|
|
51
|
+
end
|
|
52
|
+
MODEL
|
|
53
|
+
expect(File.read('app/models/generated_table.rb')).to eq(model)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|