deimos-ruby 1.7.0.pre.beta1 → 1.8.1.pre.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -4
  3. data/CHANGELOG.md +50 -0
  4. data/Gemfile.lock +109 -75
  5. data/README.md +147 -16
  6. data/deimos-ruby.gemspec +4 -2
  7. data/docs/ARCHITECTURE.md +144 -0
  8. data/docs/CONFIGURATION.md +4 -0
  9. data/lib/deimos.rb +8 -7
  10. data/lib/deimos/active_record_consume/batch_consumption.rb +159 -0
  11. data/lib/deimos/active_record_consume/batch_slicer.rb +27 -0
  12. data/lib/deimos/active_record_consume/message_consumption.rb +58 -0
  13. data/lib/deimos/active_record_consume/schema_model_converter.rb +52 -0
  14. data/lib/deimos/active_record_consumer.rb +33 -75
  15. data/lib/deimos/batch_consumer.rb +2 -142
  16. data/lib/deimos/config/configuration.rb +8 -10
  17. data/lib/deimos/consume/batch_consumption.rb +150 -0
  18. data/lib/deimos/consume/message_consumption.rb +94 -0
  19. data/lib/deimos/consumer.rb +79 -72
  20. data/lib/deimos/instrumentation.rb +10 -5
  21. data/lib/deimos/kafka_message.rb +1 -1
  22. data/lib/deimos/kafka_topic_info.rb +21 -2
  23. data/lib/deimos/message.rb +6 -1
  24. data/lib/deimos/schema_backends/avro_base.rb +33 -1
  25. data/lib/deimos/schema_backends/avro_schema_coercer.rb +30 -11
  26. data/lib/deimos/schema_backends/base.rb +21 -2
  27. data/lib/deimos/utils/db_poller.rb +6 -6
  28. data/lib/deimos/utils/db_producer.rb +57 -15
  29. data/lib/deimos/utils/deadlock_retry.rb +68 -0
  30. data/lib/deimos/utils/lag_reporter.rb +19 -26
  31. data/lib/deimos/utils/schema_controller_mixin.rb +111 -0
  32. data/lib/deimos/version.rb +1 -1
  33. data/lib/generators/deimos/active_record/templates/migration.rb.tt +28 -0
  34. data/lib/generators/deimos/active_record/templates/model.rb.tt +5 -0
  35. data/lib/generators/deimos/active_record_generator.rb +79 -0
  36. data/lib/generators/deimos/db_backend/templates/migration +1 -0
  37. data/lib/generators/deimos/db_backend/templates/rails3_migration +1 -0
  38. data/spec/active_record_batch_consumer_spec.rb +481 -0
  39. data/spec/active_record_consume/batch_slicer_spec.rb +42 -0
  40. data/spec/active_record_consume/schema_model_converter_spec.rb +105 -0
  41. data/spec/active_record_consumer_spec.rb +3 -11
  42. data/spec/batch_consumer_spec.rb +24 -7
  43. data/spec/config/configuration_spec.rb +4 -0
  44. data/spec/consumer_spec.rb +6 -6
  45. data/spec/deimos_spec.rb +57 -49
  46. data/spec/generators/active_record_generator_spec.rb +56 -0
  47. data/spec/handlers/my_batch_consumer.rb +6 -1
  48. data/spec/handlers/my_consumer.rb +6 -1
  49. data/spec/kafka_listener_spec.rb +54 -0
  50. data/spec/kafka_topic_info_spec.rb +39 -16
  51. data/spec/message_spec.rb +19 -0
  52. data/spec/producer_spec.rb +34 -0
  53. data/spec/schemas/com/my-namespace/Generated.avsc +71 -0
  54. data/spec/schemas/com/my-namespace/MyNestedSchema.avsc +55 -0
  55. data/spec/schemas/com/my-namespace/MySchemaCompound-key.avsc +18 -0
  56. data/spec/schemas/com/my-namespace/Wibble.avsc +43 -0
  57. data/spec/schemas/com/my-namespace/request/Index.avsc +11 -0
  58. data/spec/schemas/com/my-namespace/request/UpdateRequest.avsc +11 -0
  59. data/spec/schemas/com/my-namespace/response/Index.avsc +11 -0
  60. data/spec/schemas/com/my-namespace/response/UpdateResponse.avsc +11 -0
  61. data/spec/spec_helper.rb +24 -0
  62. data/spec/utils/db_poller_spec.rb +2 -2
  63. data/spec/utils/db_producer_spec.rb +84 -10
  64. data/spec/utils/deadlock_retry_spec.rb +74 -0
  65. data/spec/utils/lag_reporter_spec.rb +29 -22
  66. data/spec/utils/schema_controller_mixin_spec.rb +68 -0
  67. metadata +87 -30
  68. data/lib/deimos/base_consumer.rb +0 -100
  69. data/lib/deimos/utils/executor.rb +0 -124
  70. data/lib/deimos/utils/platform_schema_validation.rb +0 -0
  71. data/lib/deimos/utils/signal_handler.rb +0 -68
  72. data/spec/utils/executor_spec.rb +0 -53
  73. data/spec/utils/signal_handler_spec.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab8ac284db2c98dac5624caf5bf75118ad89fb9ec6e1f3109f15373f2bf4c8be
4
- data.tar.gz: 7d26a7d8d163ab4783638c9393bea2d1a7c8f364a7eed2ea4cb699cbcbafd244
3
+ metadata.gz: 380e0a86786dc4b308858186e5f97a102d13e0d0ac72ca172e941d42b6dfb81a
4
+ data.tar.gz: ca99315cf3ee096160c24f15d194ce73d77d95b1e7c27b3454e2a5e4165ef156
5
5
  SHA512:
6
- metadata.gz: 2610223a8d8c2546dad4037e4d2b1845e77372b304f4c072c269316bceed4a6626bd36d3541561d91e1c68a06ed891c051feb16a1800763cf805061c05cadc58
7
- data.tar.gz: 3916fa546b45182b987b0409d51bcce96c5a1beee449722861819f76377258e7ccb5700f50d2c0d8d1791986ed4f5d19b7c989cdcdbe77d1289e8531eb24ba15
6
+ metadata.gz: 8aa602000e702a9ce3c271b0796f4ea864fdc0acaf0852fdf7bdc3bf51e0eaf2df3265420e2558f37e3c174a5a555d43920323bb3a1539753b8821ae00ad6f32
7
+ data.tar.gz: c505ef8b587d2a405f9773a3c0f5a178f27811a071a4579ecfbe46c9f75759f1375b773949a384cdd465638ca7e95c53e6e34d8a1b7dd27e5128e03a90c0c3b1
@@ -5,6 +5,7 @@ AllCops:
5
5
  Exclude:
6
6
  - lib/deimos/monkey_patches/*.rb
7
7
  - vendor/**/*
8
+ - Guardfile
8
9
  NewCops: enable
9
10
 
10
11
  # class Plumbus
@@ -36,7 +37,7 @@ Layout/EmptyLinesAroundBlockBody:
36
37
  Enabled: false
37
38
 
38
39
  Layout/LineLength:
39
- Max: 100
40
+ Max: 120
40
41
  Severity: refactor
41
42
  Exclude:
42
43
  - 'spec/**/*'
@@ -77,13 +78,14 @@ Lint/UnusedMethodArgument:
77
78
 
78
79
  Metrics/AbcSize:
79
80
  Severity: refactor
80
- Max: 20
81
+ Max: 25
81
82
 
82
83
  Metrics/BlockLength:
83
- Severity: refactor
84
+ Enabled: false
84
85
 
85
86
  Metrics/ClassLength:
86
87
  Severity: refactor
88
+ Max: 500
87
89
 
88
90
  Metrics/CyclomaticComplexity:
89
91
  Severity: refactor
@@ -91,10 +93,11 @@ Metrics/CyclomaticComplexity:
91
93
 
92
94
  Metrics/MethodLength:
93
95
  Severity: refactor
94
- Max: 30
96
+ Max: 50
95
97
 
96
98
  Metrics/ModuleLength:
97
99
  Severity: refactor
100
+ Max: 200
98
101
 
99
102
  Metrics/ParameterLists:
100
103
  Max: 5
@@ -102,6 +105,7 @@ Metrics/ParameterLists:
102
105
 
103
106
  Metrics/PerceivedComplexity:
104
107
  Severity: refactor
108
+ Max: 10
105
109
 
106
110
  # Use alias_method instead of alias
107
111
  Style/Alias:
@@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
+ ## 1.8.1-beta3 - 2020-08-05
11
+
12
+ ### Fixes :wrench:
13
+ - Simplify decoding messages and handle producer not found
14
+ - Consolidate types in sub-records recursively
15
+ (fixes [#72](https://github.com/flipp-oss/deimos/issues/72))
16
+
17
+ ## 1.8.1-beta2 - 2020-07-28
18
+
19
+ ### Features :star:
20
+ - Add `SchemaControllerMixin` to encode and decode schema-encoded
21
+ payloads in Rails controllers.
22
+
23
+ ## 1.8.1-beta1 - 2020-07-22
24
+
25
+ ### Fixes :wrench:
26
+ - Retry deleting messages without resending the batch if the
27
+ delete fails (fixes [#34](https://github.com/flipp-oss/deimos/issues/34))
28
+ - Delete messages in batches rather than all at once to
29
+ cut down on the chance of a deadlock.
30
+
31
+ ### Features :star:
32
+ - Add `last_processed_at` to `kafka_topic_info` to ensure
33
+ that wait metrics are accurate in cases where records
34
+ get created with an old `created_at` time (e.g. for
35
+ long-running transactions).
36
+ - Add generator for ActiveRecord models and migrations (fixes [#6](https://github.com/flipp-oss/deimos/issues/6))
37
+
38
+ ## 1.8.0-beta2 - 2020-07-08
39
+
40
+ ### Fixes :wrench:
41
+ - Fix crash with batch consumption due to not having ActiveSupport::Concern
42
+
43
+ ### Features :star:
44
+ - Add `first_offset` to the metadata sent via the batch
45
+
46
+ ## 1.8.0-beta1 - 2020-07-06
47
+ ### Features :star:
48
+ - Added `ActiveRecordConsumer` batch mode
49
+
50
+ ### Fixes :wrench:
51
+ - Fixes `send_produce_error` to decode `failed_messages` with built-in decoder.
52
+ - Lag calculation can be incorrect if no messages are being consumed.
53
+ - Fixed bug where printing messages on a MessageSizeTooLarge
54
+ error didn't work.
55
+
56
+ ### Roadmap
57
+ - Moved SignalHandler and Executor to the `sigurd` gem.
58
+
59
+ ## 1.7.0-beta1 - 2020-05-12
10
60
  ### Features :star:
11
61
  - Added the DB Poller feature / process.
12
62
 
@@ -1,79 +1,95 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- deimos-ruby (1.7.0.pre.beta1)
4
+ deimos-ruby (1.8.1.pre.beta3)
5
5
  avro_turf (~> 0.11)
6
6
  phobos (~> 1.9)
7
7
  ruby-kafka (~> 0.7)
8
+ sigurd (= 0.0.1)
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
11
12
  specs:
12
- actioncable (5.2.4.2)
13
- actionpack (= 5.2.4.2)
13
+ actioncable (6.0.3.2)
14
+ actionpack (= 6.0.3.2)
14
15
  nio4r (~> 2.0)
15
16
  websocket-driver (>= 0.6.1)
16
- actionmailer (5.2.4.2)
17
- actionpack (= 5.2.4.2)
18
- actionview (= 5.2.4.2)
19
- activejob (= 5.2.4.2)
17
+ actionmailbox (6.0.3.2)
18
+ actionpack (= 6.0.3.2)
19
+ activejob (= 6.0.3.2)
20
+ activerecord (= 6.0.3.2)
21
+ activestorage (= 6.0.3.2)
22
+ activesupport (= 6.0.3.2)
23
+ mail (>= 2.7.1)
24
+ actionmailer (6.0.3.2)
25
+ actionpack (= 6.0.3.2)
26
+ actionview (= 6.0.3.2)
27
+ activejob (= 6.0.3.2)
20
28
  mail (~> 2.5, >= 2.5.4)
21
29
  rails-dom-testing (~> 2.0)
22
- actionpack (5.2.4.2)
23
- actionview (= 5.2.4.2)
24
- activesupport (= 5.2.4.2)
30
+ actionpack (6.0.3.2)
31
+ actionview (= 6.0.3.2)
32
+ activesupport (= 6.0.3.2)
25
33
  rack (~> 2.0, >= 2.0.8)
26
34
  rack-test (>= 0.6.3)
27
35
  rails-dom-testing (~> 2.0)
28
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
29
- actionview (5.2.4.2)
30
- activesupport (= 5.2.4.2)
36
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
37
+ actiontext (6.0.3.2)
38
+ actionpack (= 6.0.3.2)
39
+ activerecord (= 6.0.3.2)
40
+ activestorage (= 6.0.3.2)
41
+ activesupport (= 6.0.3.2)
42
+ nokogiri (>= 1.8.5)
43
+ actionview (6.0.3.2)
44
+ activesupport (= 6.0.3.2)
31
45
  builder (~> 3.1)
32
46
  erubi (~> 1.4)
33
47
  rails-dom-testing (~> 2.0)
34
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
35
- activejob (5.2.4.2)
36
- activesupport (= 5.2.4.2)
48
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
49
+ activejob (6.0.3.2)
50
+ activesupport (= 6.0.3.2)
37
51
  globalid (>= 0.3.6)
38
- activemodel (5.2.4.2)
39
- activesupport (= 5.2.4.2)
40
- activerecord (5.2.4.2)
41
- activemodel (= 5.2.4.2)
42
- activesupport (= 5.2.4.2)
43
- arel (>= 9.0)
44
- activerecord-import (1.0.4)
52
+ activemodel (6.0.3.2)
53
+ activesupport (= 6.0.3.2)
54
+ activerecord (6.0.3.2)
55
+ activemodel (= 6.0.3.2)
56
+ activesupport (= 6.0.3.2)
57
+ activerecord-import (1.0.5)
45
58
  activerecord (>= 3.2)
46
- activestorage (5.2.4.2)
47
- actionpack (= 5.2.4.2)
48
- activerecord (= 5.2.4.2)
59
+ activestorage (6.0.3.2)
60
+ actionpack (= 6.0.3.2)
61
+ activejob (= 6.0.3.2)
62
+ activerecord (= 6.0.3.2)
49
63
  marcel (~> 0.3.1)
50
- activesupport (5.2.4.2)
64
+ activesupport (6.0.3.2)
51
65
  concurrent-ruby (~> 1.0, >= 1.0.2)
52
66
  i18n (>= 0.7, < 2)
53
67
  minitest (~> 5.1)
54
68
  tzinfo (~> 1.1)
55
- arel (9.0.0)
56
- ast (2.4.0)
69
+ zeitwerk (~> 2.2, >= 2.2.2)
70
+ ast (2.4.1)
57
71
  avro (1.9.2)
58
72
  multi_json
59
73
  avro_turf (0.11.0)
60
74
  avro (>= 1.7.7, < 1.10)
61
75
  excon (~> 0.45)
62
76
  builder (3.2.4)
63
- coderay (1.1.2)
77
+ coderay (1.1.3)
64
78
  concurrent-ruby (1.1.6)
65
79
  concurrent-ruby-ext (1.1.6)
66
80
  concurrent-ruby (= 1.1.6)
67
81
  crass (1.0.6)
68
- ddtrace (0.35.1)
82
+ database_cleaner (1.8.5)
83
+ ddtrace (0.37.0)
69
84
  msgpack
70
- diff-lcs (1.3)
71
- digest-crc (0.5.1)
72
- dogstatsd-ruby (4.8.0)
85
+ diff-lcs (1.4.4)
86
+ digest-crc (0.6.1)
87
+ rake (~> 13.0)
88
+ dogstatsd-ruby (4.8.1)
73
89
  erubi (1.9.0)
74
- excon (0.73.0)
90
+ excon (0.76.0)
75
91
  exponential-backoff (0.0.4)
76
- ffi (1.12.2)
92
+ ffi (1.13.1)
77
93
  formatador (0.2.5)
78
94
  globalid (0.4.2)
79
95
  activesupport (>= 4.2.0)
@@ -94,20 +110,19 @@ GEM
94
110
  guard-rubocop (1.3.0)
95
111
  guard (~> 2.0)
96
112
  rubocop (~> 0.20)
97
- i18n (1.8.2)
113
+ i18n (1.8.4)
98
114
  concurrent-ruby (~> 1.0)
99
- jaro_winkler (1.5.4)
100
115
  listen (3.2.1)
101
116
  rb-fsevent (~> 0.10, >= 0.10.3)
102
117
  rb-inotify (~> 0.9, >= 0.9.10)
103
118
  little-plugger (1.1.4)
104
- logging (2.2.2)
119
+ logging (2.3.0)
105
120
  little-plugger (~> 1.1)
106
- multi_json (~> 1.10)
107
- loofah (2.5.0)
121
+ multi_json (~> 1.14)
122
+ loofah (2.6.0)
108
123
  crass (~> 1.0.2)
109
124
  nokogiri (>= 1.5.9)
110
- lumberjack (1.2.4)
125
+ lumberjack (1.2.6)
111
126
  mail (2.7.1)
112
127
  mini_mime (>= 0.1.1)
113
128
  marcel (0.3.3)
@@ -116,20 +131,20 @@ GEM
116
131
  mimemagic (0.3.5)
117
132
  mini_mime (1.0.2)
118
133
  mini_portile2 (2.4.0)
119
- minitest (5.14.0)
134
+ minitest (5.14.1)
120
135
  msgpack (1.3.3)
121
- multi_json (1.14.1)
136
+ multi_json (1.15.0)
122
137
  mysql2 (0.5.3)
123
138
  nenv (0.3.0)
124
139
  nio4r (2.5.2)
125
- nokogiri (1.10.9)
140
+ nokogiri (1.10.10)
126
141
  mini_portile2 (~> 2.4.0)
127
142
  notiffany (0.1.3)
128
143
  nenv (~> 0.1)
129
144
  shellany (~> 0.0)
130
- parallel (1.19.1)
131
- parser (2.7.1.2)
132
- ast (~> 2.4.0)
145
+ parallel (1.19.2)
146
+ parser (2.7.1.4)
147
+ ast (~> 2.4.1)
133
148
  pg (1.2.3)
134
149
  phobos (1.9.0)
135
150
  activesupport (>= 3.0.0)
@@ -142,38 +157,41 @@ GEM
142
157
  pry (0.13.1)
143
158
  coderay (~> 1.1)
144
159
  method_source (~> 1.0)
145
- rack (2.2.2)
160
+ rack (2.2.3)
146
161
  rack-test (1.1.0)
147
162
  rack (>= 1.0, < 3)
148
- rails (5.2.4.2)
149
- actioncable (= 5.2.4.2)
150
- actionmailer (= 5.2.4.2)
151
- actionpack (= 5.2.4.2)
152
- actionview (= 5.2.4.2)
153
- activejob (= 5.2.4.2)
154
- activemodel (= 5.2.4.2)
155
- activerecord (= 5.2.4.2)
156
- activestorage (= 5.2.4.2)
157
- activesupport (= 5.2.4.2)
163
+ rails (6.0.3.2)
164
+ actioncable (= 6.0.3.2)
165
+ actionmailbox (= 6.0.3.2)
166
+ actionmailer (= 6.0.3.2)
167
+ actionpack (= 6.0.3.2)
168
+ actiontext (= 6.0.3.2)
169
+ actionview (= 6.0.3.2)
170
+ activejob (= 6.0.3.2)
171
+ activemodel (= 6.0.3.2)
172
+ activerecord (= 6.0.3.2)
173
+ activestorage (= 6.0.3.2)
174
+ activesupport (= 6.0.3.2)
158
175
  bundler (>= 1.3.0)
159
- railties (= 5.2.4.2)
176
+ railties (= 6.0.3.2)
160
177
  sprockets-rails (>= 2.0.0)
161
178
  rails-dom-testing (2.0.3)
162
179
  activesupport (>= 4.2.0)
163
180
  nokogiri (>= 1.6)
164
181
  rails-html-sanitizer (1.3.0)
165
182
  loofah (~> 2.3)
166
- railties (5.2.4.2)
167
- actionpack (= 5.2.4.2)
168
- activesupport (= 5.2.4.2)
183
+ railties (6.0.3.2)
184
+ actionpack (= 6.0.3.2)
185
+ activesupport (= 6.0.3.2)
169
186
  method_source
170
187
  rake (>= 0.8.7)
171
- thor (>= 0.19.0, < 2.0)
188
+ thor (>= 0.20.3, < 2.0)
172
189
  rainbow (3.0.0)
173
190
  rake (13.0.1)
174
191
  rb-fsevent (0.10.4)
175
192
  rb-inotify (0.10.1)
176
193
  ffi (~> 1.0)
194
+ regexp_parser (1.7.1)
177
195
  rexml (3.2.4)
178
196
  rspec (3.9.0)
179
197
  rspec-core (~> 3.9.0)
@@ -181,30 +199,44 @@ GEM
181
199
  rspec-mocks (~> 3.9.0)
182
200
  rspec-core (3.9.2)
183
201
  rspec-support (~> 3.9.3)
184
- rspec-expectations (3.9.1)
202
+ rspec-expectations (3.9.2)
185
203
  diff-lcs (>= 1.2.0, < 2.0)
186
204
  rspec-support (~> 3.9.0)
187
205
  rspec-mocks (3.9.1)
188
206
  diff-lcs (>= 1.2.0, < 2.0)
189
207
  rspec-support (~> 3.9.0)
208
+ rspec-rails (4.0.1)
209
+ actionpack (>= 4.2)
210
+ activesupport (>= 4.2)
211
+ railties (>= 4.2)
212
+ rspec-core (~> 3.9)
213
+ rspec-expectations (~> 3.9)
214
+ rspec-mocks (~> 3.9)
215
+ rspec-support (~> 3.9)
190
216
  rspec-support (3.9.3)
191
217
  rspec_junit_formatter (0.4.1)
192
218
  rspec-core (>= 2, < 4, != 2.12.0)
193
- rubocop (0.82.0)
194
- jaro_winkler (~> 1.5.1)
219
+ rubocop (0.88.0)
195
220
  parallel (~> 1.10)
196
- parser (>= 2.7.0.1)
221
+ parser (>= 2.7.1.1)
197
222
  rainbow (>= 2.2.2, < 4.0)
223
+ regexp_parser (>= 1.7)
198
224
  rexml
225
+ rubocop-ast (>= 0.1.0, < 1.0)
199
226
  ruby-progressbar (~> 1.7)
200
227
  unicode-display_width (>= 1.4.0, < 2.0)
201
- rubocop-rspec (1.39.0)
202
- rubocop (>= 0.68.1)
228
+ rubocop-ast (0.2.0)
229
+ parser (>= 2.7.0.1)
230
+ rubocop-rspec (1.42.0)
231
+ rubocop (>= 0.87.0)
203
232
  ruby-kafka (0.7.10)
204
233
  digest-crc
205
234
  ruby-progressbar (1.10.1)
206
235
  shellany (0.0.1)
207
- sprockets (4.0.0)
236
+ sigurd (0.0.1)
237
+ concurrent-ruby (~> 1)
238
+ exponential-backoff
239
+ sprockets (4.0.2)
208
240
  concurrent-ruby (~> 1.0)
209
241
  rack (> 1, < 3)
210
242
  sprockets-rails (3.2.1)
@@ -217,17 +249,18 @@ GEM
217
249
  tzinfo (1.2.7)
218
250
  thread_safe (~> 0.1)
219
251
  unicode-display_width (1.7.0)
220
- websocket-driver (0.7.1)
252
+ websocket-driver (0.7.3)
221
253
  websocket-extensions (>= 0.1.0)
222
- websocket-extensions (0.1.4)
254
+ websocket-extensions (0.1.5)
255
+ zeitwerk (2.4.0)
223
256
 
224
257
  PLATFORMS
225
258
  ruby
226
259
 
227
260
  DEPENDENCIES
228
- activerecord (~> 5.2)
229
261
  activerecord-import
230
262
  avro (~> 1.9)
263
+ database_cleaner (~> 1.7)
231
264
  ddtrace (~> 0.11)
232
265
  deimos-ruby!
233
266
  dogstatsd-ruby (~> 4.2)
@@ -236,9 +269,10 @@ DEPENDENCIES
236
269
  guard-rubocop (~> 1)
237
270
  mysql2 (~> 0.5)
238
271
  pg (~> 1.1)
239
- rails (~> 5.2, >= 5.2.4.2)
272
+ rails (~> 6)
240
273
  rake (~> 13)
241
274
  rspec (~> 3)
275
+ rspec-rails (~> 4)
242
276
  rspec_junit_formatter (~> 0.3)
243
277
  rubocop (~> 0.72)
244
278
  rubocop-rspec (~> 1.27)
data/README.md CHANGED
@@ -22,6 +22,7 @@ Built on Phobos and hence Ruby-Kafka.
22
22
  * [Kafka Message Keys](#kafka-message-keys)
23
23
  * [Consumers](#consumers)
24
24
  * [Rails Integration](#rails-integration)
25
+ * [Controller Mixin](#controller-mixin)
25
26
  * [Database Backend](#database-backend)
26
27
  * [Database Poller](#database-poller)
27
28
  * [Running Consumers](#running-consumers)
@@ -314,28 +315,19 @@ messages as an array and then process them together. This can improve
314
315
  consumer throughput, depending on the use case. Batch consumers behave like
315
316
  other consumers in regards to key and payload decoding, etc.
316
317
 
317
- To enable batch consumption, ensure that the `delivery` property is set to `inline_batch`. For example:
318
+ To enable batch consumption, ensure that the `delivery` property of your
319
+ consumer is set to `inline_batch`.
318
320
 
319
- ```ruby
320
- Deimos.configure do
321
- consumer do
322
- class_name 'Consumers::MyBatchConsumer'
323
- topic 'my_batched_topic'
324
- group_id 'my_group_id'
325
- delivery :inline_batch
326
- end
327
- end
328
- ```
329
-
330
- Batch consumers must inherit from the Deimos::BatchConsumer class as in
331
- this sample:
321
+ Batch consumers will invoke the `consume_batch` method instead of `consume`
322
+ as in this example:
332
323
 
333
324
  ```ruby
334
- class MyBatchConsumer < Deimos::BatchConsumer
325
+ class MyBatchConsumer < Deimos::Consumer
335
326
 
336
327
  def consume_batch(payloads, metadata)
337
328
  # payloads is an array of schema-decoded hashes.
338
- # metadata is a hash that contains information like :keys and :topic.
329
+ # metadata is a hash that contains information like :keys, :topic,
330
+ # and :first_offset.
339
331
  # Keys are automatically decoded and available as an array with
340
332
  # the same cardinality as the payloads. If you need to iterate
341
333
  # over payloads and keys together, you can use something like this:
@@ -456,6 +448,58 @@ class Widget < ActiveRecord::Base
456
448
  end
457
449
  ```
458
450
 
451
+ ### Controller Mixin
452
+
453
+ Deimos comes with a mixin for `ActionController` which automatically encodes and decodes schema
454
+ payloads. There are some advantages to encoding your data in e.g. Avro rather than straight JSON,
455
+ particularly if your service is talking to another backend service rather than the front-end
456
+ browser:
457
+
458
+ * It enforces a contract between services. Solutions like [OpenAPI](https://swagger.io/specification/)
459
+ do this as well, but in order for the client to know the contract, usually some kind of code
460
+ generation has to happen. Using schemas ensures both sides know the contract without having to change code.
461
+ In addition, OpenAPI is now a huge and confusing format, and using simpler schema formats
462
+ can be beneficial.
463
+ * Using Avro or Protobuf ensures both forwards and backwards compatibility,
464
+ which reduces the need for versioning since both sides can simply ignore fields they aren't aware
465
+ of.
466
+ * Encoding and decoding using Avro or Protobuf is generally faster than straight JSON, and
467
+ results in smaller payloads and therefore less network traffic.
468
+
469
+ To use the mixin, add the following to your `WhateverController`:
470
+
471
+ ```ruby
472
+ class WhateverController < ApplicationController
473
+ include Deimos::Utils::SchemaControllerMixin
474
+
475
+ request_namespace 'my.namespace.requests'
476
+ response_namespace 'my.namespace.responses'
477
+
478
+ # Add a "schemas" line for all routes that should encode/decode schemas.
479
+ # Default is to match the schema name to the route name.
480
+ schemas :index
481
+ # will look for: my.namespace.requests.Index.avsc
482
+ # my.namespace.responses.Index.avsc
483
+
484
+ # If all routes use the default, you can add them all at once
485
+ schemas :index, :show, :update
486
+
487
+ # Different schemas can be specified as well
488
+ schemas :index, :show, request: 'IndexRequest', response: 'IndexResponse'
489
+
490
+ # To access the encoded data, use the `payload` helper method, and to render it back,
491
+ # use the `render_schema` method.
492
+
493
+ def index
494
+ response = { 'response_id' => payload['request_id'] + 'hi mom' }
495
+ render_schema(response)
496
+ end
497
+ end
498
+ ```
499
+
500
+ To make use of this feature, your requests and responses need to have the correct content type.
501
+ For Avro content, this is the `avro/binary` content type.
502
+
459
503
  # Database Backend
460
504
 
461
505
  Deimos provides a way to allow Kafka messages to be created inside a
@@ -533,12 +577,14 @@ class MyConsumer < Deimos::ActiveRecordConsumer
533
577
 
534
578
  # Optional override of the way to fetch records based on payload and
535
579
  # key. Default is to use the key to search the primary key of the table.
580
+ # Only used in non-batch mode.
536
581
  def fetch_record(klass, payload, key)
537
582
  super
538
583
  end
539
584
 
540
585
  # Optional override on how to set primary key for new records.
541
586
  # Default is to set the class's primary key to the message's decoded key.
587
+ # Only used in non-batch mode.
542
588
  def assign_key(record, payload, key)
543
589
  super
544
590
  end
@@ -546,6 +592,7 @@ class MyConsumer < Deimos::ActiveRecordConsumer
546
592
  # Optional override of the default behavior, which is to call `destroy`
547
593
  # on the record - e.g. you can replace this with "archiving" the record
548
594
  # in some way.
595
+ # Only used in non-batch mode.
549
596
  def destroy_record(record)
550
597
  super
551
598
  end
@@ -555,6 +602,87 @@ class MyConsumer < Deimos::ActiveRecordConsumer
555
602
  def record_attributes(payload)
556
603
  super.merge(:some_field => 'some_value')
557
604
  end
605
+
606
+ # Optional override to change the attributes used for identifying records
607
+ def record_key(payload)
608
+ super
609
+ end
610
+ end
611
+ ```
612
+
613
+ #### Generating Tables and Models
614
+
615
+ Deimos provides a generator that takes an existing schema and generates a
616
+ database table based on its fields. By default, any complex sub-types (such as
617
+ records or arrays) are turned into JSON (if supported) or string columns.
618
+
619
+ Before running this migration, you must first copy the schema into your repo
620
+ in the correct path (in the example above, you would need to have a file
621
+ `{SCHEMA_ROOT}/com/my-namespace/MySchema.avsc`).
622
+
623
+ To generate a model and migration, run the following:
624
+
625
+ rails g deimos:active_record TABLE_NAME FULL_SCHEMA_NAME
626
+
627
+ Example:
628
+
629
+ rails g deimos:active_record my_table com.my-namespace.MySchema
630
+
631
+ ...would generate:
632
+
633
+ db/migrate/1234_create_my_table.rb
634
+ app/models/my_table.rb
635
+
636
+ #### Batch Consumers
637
+
638
+ Deimos also provides a batch consumption mode for `ActiveRecordConsumer` which
639
+ processes groups of messages at once using the ActiveRecord backend.
640
+
641
+ Batch ActiveRecord consumers make use of the
642
+ [activerecord-import](https://github.com/zdennis/activerecord-import) to insert
643
+ or update multiple records in bulk SQL statements. This reduces processing
644
+ time at the cost of skipping ActiveRecord callbacks for individual records.
645
+ Deleted records (tombstones) are grouped into `delete_all` calls and thus also
646
+ skip `destroy` callbacks.
647
+
648
+ Batch consumption is used when the `delivery` setting for your consumer is set to `inline_batch`.
649
+
650
+ **Note**: Currently, batch consumption only supports only primary keys as identifiers out of the box. See
651
+ [the specs](spec/active_record_batch_consumer_spec.rb) for an example of how to use compound keys.
652
+
653
+ By default, batches will be compacted before processing, i.e. only the last
654
+ message for each unique key in a batch will actually be processed. To change
655
+ this behaviour, call `compacted false` inside of your consumer definition.
656
+
657
+ A sample batch consumer would look as follows:
658
+
659
+ ```ruby
660
+ class MyConsumer < Deimos::ActiveRecordConsumer
661
+ schema 'MySchema'
662
+ key_config field: 'my_field'
663
+ record_class Widget
664
+
665
+ # Controls whether the batch is compacted before consuming.
666
+ # If true, only the last message for each unique key in a batch will be
667
+ # processed.
668
+ # If false, messages will be grouped into "slices" of independent keys
669
+ # and each slice will be imported separately.
670
+ #
671
+ # compacted false
672
+
673
+
674
+ # Optional override of the default behavior, which is to call `delete_all`
675
+ # on the associated records - e.g. you can replace this with setting a deleted
676
+ # flag on the record.
677
+ def remove_records(records)
678
+ super
679
+ end
680
+
681
+ # Optional override to change the attributes of the record before they
682
+ # are saved.
683
+ def record_attributes(payload)
684
+ super.merge(:some_field => 'some_value')
685
+ end
558
686
  end
559
687
  ```
560
688
 
@@ -853,6 +981,9 @@ Deimos::Utils::InlineConsumer.get_messages_for(
853
981
 
854
982
  Bug reports and pull requests are welcome on GitHub at https://github.com/flipp-oss/deimos .
855
983
 
984
+ We have more information on the [internal architecture](docs/ARCHITECTURE.md) of Deimos
985
+ for contributors!
986
+
856
987
  ### Linting
857
988
 
858
989
  Deimos uses Rubocop to lint the code. Please run Rubocop on your code