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.
Files changed (146) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +83 -0
  3. data/.gitignore +41 -0
  4. data/.gitmodules +0 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +333 -0
  7. data/.ruby-gemset +1 -0
  8. data/.ruby-version +1 -0
  9. data/CHANGELOG.md +349 -0
  10. data/CODE_OF_CONDUCT.md +77 -0
  11. data/Dockerfile +23 -0
  12. data/Gemfile +6 -0
  13. data/Gemfile.lock +286 -0
  14. data/Guardfile +22 -0
  15. data/LICENSE.md +195 -0
  16. data/README.md +1099 -0
  17. data/Rakefile +13 -0
  18. data/bin/deimos +4 -0
  19. data/deimos-ruby.gemspec +44 -0
  20. data/docker-compose.yml +71 -0
  21. data/docs/ARCHITECTURE.md +140 -0
  22. data/docs/CONFIGURATION.md +236 -0
  23. data/docs/DATABASE_BACKEND.md +147 -0
  24. data/docs/INTEGRATION_TESTS.md +52 -0
  25. data/docs/PULL_REQUEST_TEMPLATE.md +35 -0
  26. data/docs/UPGRADING.md +128 -0
  27. data/lib/deimos-temp-fork.rb +95 -0
  28. data/lib/deimos/active_record_consume/batch_consumption.rb +164 -0
  29. data/lib/deimos/active_record_consume/batch_slicer.rb +27 -0
  30. data/lib/deimos/active_record_consume/message_consumption.rb +79 -0
  31. data/lib/deimos/active_record_consume/schema_model_converter.rb +52 -0
  32. data/lib/deimos/active_record_consumer.rb +67 -0
  33. data/lib/deimos/active_record_producer.rb +87 -0
  34. data/lib/deimos/backends/base.rb +32 -0
  35. data/lib/deimos/backends/db.rb +41 -0
  36. data/lib/deimos/backends/kafka.rb +33 -0
  37. data/lib/deimos/backends/kafka_async.rb +33 -0
  38. data/lib/deimos/backends/test.rb +20 -0
  39. data/lib/deimos/batch_consumer.rb +7 -0
  40. data/lib/deimos/config/configuration.rb +381 -0
  41. data/lib/deimos/config/phobos_config.rb +137 -0
  42. data/lib/deimos/consume/batch_consumption.rb +150 -0
  43. data/lib/deimos/consume/message_consumption.rb +94 -0
  44. data/lib/deimos/consumer.rb +104 -0
  45. data/lib/deimos/instrumentation.rb +76 -0
  46. data/lib/deimos/kafka_message.rb +60 -0
  47. data/lib/deimos/kafka_source.rb +128 -0
  48. data/lib/deimos/kafka_topic_info.rb +102 -0
  49. data/lib/deimos/message.rb +79 -0
  50. data/lib/deimos/metrics/datadog.rb +47 -0
  51. data/lib/deimos/metrics/mock.rb +39 -0
  52. data/lib/deimos/metrics/provider.rb +36 -0
  53. data/lib/deimos/monkey_patches/phobos_cli.rb +35 -0
  54. data/lib/deimos/monkey_patches/phobos_producer.rb +51 -0
  55. data/lib/deimos/poll_info.rb +9 -0
  56. data/lib/deimos/producer.rb +224 -0
  57. data/lib/deimos/railtie.rb +8 -0
  58. data/lib/deimos/schema_backends/avro_base.rb +140 -0
  59. data/lib/deimos/schema_backends/avro_local.rb +30 -0
  60. data/lib/deimos/schema_backends/avro_schema_coercer.rb +119 -0
  61. data/lib/deimos/schema_backends/avro_schema_registry.rb +34 -0
  62. data/lib/deimos/schema_backends/avro_validation.rb +21 -0
  63. data/lib/deimos/schema_backends/base.rb +150 -0
  64. data/lib/deimos/schema_backends/mock.rb +42 -0
  65. data/lib/deimos/shared_config.rb +63 -0
  66. data/lib/deimos/test_helpers.rb +360 -0
  67. data/lib/deimos/tracing/datadog.rb +35 -0
  68. data/lib/deimos/tracing/mock.rb +40 -0
  69. data/lib/deimos/tracing/provider.rb +29 -0
  70. data/lib/deimos/utils/db_poller.rb +150 -0
  71. data/lib/deimos/utils/db_producer.rb +243 -0
  72. data/lib/deimos/utils/deadlock_retry.rb +68 -0
  73. data/lib/deimos/utils/inline_consumer.rb +150 -0
  74. data/lib/deimos/utils/lag_reporter.rb +175 -0
  75. data/lib/deimos/utils/schema_controller_mixin.rb +115 -0
  76. data/lib/deimos/version.rb +5 -0
  77. data/lib/generators/deimos/active_record/templates/migration.rb.tt +28 -0
  78. data/lib/generators/deimos/active_record/templates/model.rb.tt +5 -0
  79. data/lib/generators/deimos/active_record_generator.rb +79 -0
  80. data/lib/generators/deimos/db_backend/templates/migration +25 -0
  81. data/lib/generators/deimos/db_backend/templates/rails3_migration +31 -0
  82. data/lib/generators/deimos/db_backend_generator.rb +48 -0
  83. data/lib/generators/deimos/db_poller/templates/migration +11 -0
  84. data/lib/generators/deimos/db_poller/templates/rails3_migration +16 -0
  85. data/lib/generators/deimos/db_poller_generator.rb +48 -0
  86. data/lib/tasks/deimos.rake +34 -0
  87. data/spec/active_record_batch_consumer_spec.rb +481 -0
  88. data/spec/active_record_consume/batch_slicer_spec.rb +42 -0
  89. data/spec/active_record_consume/schema_model_converter_spec.rb +105 -0
  90. data/spec/active_record_consumer_spec.rb +154 -0
  91. data/spec/active_record_producer_spec.rb +85 -0
  92. data/spec/backends/base_spec.rb +10 -0
  93. data/spec/backends/db_spec.rb +54 -0
  94. data/spec/backends/kafka_async_spec.rb +11 -0
  95. data/spec/backends/kafka_spec.rb +11 -0
  96. data/spec/batch_consumer_spec.rb +256 -0
  97. data/spec/config/configuration_spec.rb +248 -0
  98. data/spec/consumer_spec.rb +209 -0
  99. data/spec/deimos_spec.rb +169 -0
  100. data/spec/generators/active_record_generator_spec.rb +56 -0
  101. data/spec/handlers/my_batch_consumer.rb +10 -0
  102. data/spec/handlers/my_consumer.rb +10 -0
  103. data/spec/kafka_listener_spec.rb +55 -0
  104. data/spec/kafka_source_spec.rb +381 -0
  105. data/spec/kafka_topic_info_spec.rb +111 -0
  106. data/spec/message_spec.rb +19 -0
  107. data/spec/phobos.bad_db.yml +73 -0
  108. data/spec/phobos.yml +77 -0
  109. data/spec/producer_spec.rb +498 -0
  110. data/spec/rake_spec.rb +19 -0
  111. data/spec/schema_backends/avro_base_shared.rb +199 -0
  112. data/spec/schema_backends/avro_local_spec.rb +32 -0
  113. data/spec/schema_backends/avro_schema_registry_spec.rb +32 -0
  114. data/spec/schema_backends/avro_validation_spec.rb +24 -0
  115. data/spec/schema_backends/base_spec.rb +33 -0
  116. data/spec/schemas/com/my-namespace/Generated.avsc +71 -0
  117. data/spec/schemas/com/my-namespace/MyNestedSchema.avsc +62 -0
  118. data/spec/schemas/com/my-namespace/MySchema-key.avsc +13 -0
  119. data/spec/schemas/com/my-namespace/MySchema.avsc +18 -0
  120. data/spec/schemas/com/my-namespace/MySchemaCompound-key.avsc +18 -0
  121. data/spec/schemas/com/my-namespace/MySchemaWithBooleans.avsc +18 -0
  122. data/spec/schemas/com/my-namespace/MySchemaWithDateTimes.avsc +33 -0
  123. data/spec/schemas/com/my-namespace/MySchemaWithId.avsc +28 -0
  124. data/spec/schemas/com/my-namespace/MySchemaWithUniqueId.avsc +32 -0
  125. data/spec/schemas/com/my-namespace/Wibble.avsc +43 -0
  126. data/spec/schemas/com/my-namespace/Widget.avsc +27 -0
  127. data/spec/schemas/com/my-namespace/WidgetTheSecond.avsc +27 -0
  128. data/spec/schemas/com/my-namespace/request/CreateTopic.avsc +11 -0
  129. data/spec/schemas/com/my-namespace/request/Index.avsc +11 -0
  130. data/spec/schemas/com/my-namespace/request/UpdateRequest.avsc +11 -0
  131. data/spec/schemas/com/my-namespace/response/CreateTopic.avsc +11 -0
  132. data/spec/schemas/com/my-namespace/response/Index.avsc +11 -0
  133. data/spec/schemas/com/my-namespace/response/UpdateResponse.avsc +11 -0
  134. data/spec/spec_helper.rb +267 -0
  135. data/spec/utils/db_poller_spec.rb +320 -0
  136. data/spec/utils/db_producer_spec.rb +514 -0
  137. data/spec/utils/deadlock_retry_spec.rb +74 -0
  138. data/spec/utils/inline_consumer_spec.rb +31 -0
  139. data/spec/utils/lag_reporter_spec.rb +76 -0
  140. data/spec/utils/platform_schema_validation_spec.rb +0 -0
  141. data/spec/utils/schema_controller_mixin_spec.rb +84 -0
  142. data/support/deimos-solo.png +0 -0
  143. data/support/deimos-with-name-next.png +0 -0
  144. data/support/deimos-with-name.png +0 -0
  145. data/support/flipp-logo.png +0 -0
  146. 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
@@ -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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConsumerTest
4
+ # Mock consumer
5
+ class MyBatchConsumer < Deimos::Consumer
6
+ # :no-doc:
7
+ def consume_batch
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConsumerTest
4
+ # Mock consumer
5
+ class MyConsumer < Deimos::Consumer
6
+ # :no-doc:
7
+ def consume
8
+ end
9
+ end
10
+ end