rimless 2.9.0 → 3.0.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +2 -2
  3. data/CHANGELOG.md +66 -0
  4. data/Gemfile +0 -1
  5. data/README.md +64 -62
  6. data/Rakefile +13 -4
  7. data/UPGRADING.md +491 -0
  8. data/doc/upgrade-guide-sources/README.md +221 -0
  9. data/doc/upgrade-guide-sources/dep-avro_turf-1.20.md +23 -0
  10. data/doc/upgrade-guide-sources/dep-karafka-2.0.md +117 -0
  11. data/doc/upgrade-guide-sources/dep-waterdrop-2.8.md +30 -0
  12. data/gemfiles/rails_8.0.gemfile +1 -1
  13. data/gemfiles/rails_8.1.gemfile +1 -1
  14. data/lib/rimless/compatibility/.gitkeep +0 -0
  15. data/lib/rimless/configuration.rb +80 -6
  16. data/lib/rimless/consumer/app.rb +182 -0
  17. data/lib/rimless/{karafka → consumer}/avro_deserializer.rb +8 -6
  18. data/lib/rimless/consumer/base.rb +118 -0
  19. data/lib/rimless/consumer/job.rb +35 -0
  20. data/lib/rimless/consumer/job_bridge.rb +113 -0
  21. data/lib/rimless/extensions/avro_helpers.rb +83 -0
  22. data/lib/rimless/extensions/configuration_handling.rb +77 -0
  23. data/lib/rimless/extensions/consumer.rb +20 -0
  24. data/lib/rimless/extensions/dependencies.rb +84 -0
  25. data/lib/rimless/extensions/kafka_helpers.rb +46 -0
  26. data/lib/rimless/extensions/producer.rb +103 -0
  27. data/lib/rimless/initializers/compatibility.rb +3 -4
  28. data/lib/rimless/railtie.rb +7 -7
  29. data/lib/rimless/rspec/helpers.rb +53 -13
  30. data/lib/rimless/rspec/matchers.rb +14 -11
  31. data/lib/rimless/rspec.rb +13 -29
  32. data/lib/rimless/tasks/consumer.rake +18 -6
  33. data/lib/rimless/tasks/templates/application_consumer.rb +1 -1
  34. data/lib/rimless/tasks/templates/custom_consumer.rb +1 -1
  35. data/lib/rimless/tasks/templates/custom_consumer_spec.rb +5 -4
  36. data/lib/rimless/tasks/templates/karafka.rb +5 -4
  37. data/lib/rimless/version.rb +3 -1
  38. data/lib/rimless.rb +12 -14
  39. data/rimless.gemspec +7 -9
  40. metadata +38 -67
  41. data/lib/rimless/avro_helpers.rb +0 -81
  42. data/lib/rimless/base_consumer.rb +0 -30
  43. data/lib/rimless/compatibility/karafka_1_4.rb +0 -52
  44. data/lib/rimless/configuration_handling.rb +0 -82
  45. data/lib/rimless/consumer.rb +0 -209
  46. data/lib/rimless/consumer_job.rb +0 -10
  47. data/lib/rimless/dependencies.rb +0 -69
  48. data/lib/rimless/kafka_helpers.rb +0 -104
  49. data/lib/rimless/karafka/base64_interchanger.rb +0 -32
  50. data/lib/rimless/karafka/passthrough_mapper.rb +0 -29
  51. data/lib/rimless/tasks/stats.rake +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0458c4cf20641ca5f2062e98d61d1b01a4160639a323bf866a9dbc20fdb318de'
4
- data.tar.gz: ba7ad3a77a0a23b1c32d23f77fb9464bb95de92177b44f4b726e12511f5aa127
3
+ metadata.gz: a84c6d640596ee56269220afae67746c855c1fc06c91819312c6a0a9626ed422
4
+ data.tar.gz: 7179ae84177669855f9e38b2d044ccf35ccb3405f42b94aa3275ce75907b0cea
5
5
  SHA512:
6
- metadata.gz: 5125ef4597b4fff7bf7d47a0ca6c4093998cb34dea99387eab4cbd4eb04656547be0f52fbadb6d488a4f97dcf4d0056fdf8097f3cec38031500b65bfe6af3ac0
7
- data.tar.gz: b6971835235fb6ecac1435e78d27c97d5534a2f28df60176457860bc6300e280a7420c63780b482550963af519b0a0299a0c9b0f5edbf46f64d3d92d2d3a747e
6
+ metadata.gz: 11a1fdcf0a778e581c36055cf4986880940d0fe5b41ec30b569598ad301ce51aae4cf9e2278983d33c77c0e93209b0224021d3b3ba138ac288ce83eb87a30707
7
+ data.tar.gz: c5d12b9ca331ea5b1000576c06291ecb1f8d336f2cd25f13ade6c2b509b11a83e50f1f23be3077399c70ec2356623ccfe45ee6edba0177ddeef6378e6805a6d2
data/Appraisals CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  appraise 'rails-8.0' do
4
+ gem 'activejob', '~> 8.0.0'
4
5
  gem 'activesupport', '~> 8.0.0'
5
- gem 'railties', '~> 8.0.0'
6
6
  end
7
7
 
8
8
  appraise 'rails-8.1' do
9
+ gem 'activejob', '~> 8.1.0'
9
10
  gem 'activesupport', '~> 8.1.0'
10
- gem 'railties', '~> 8.1.0'
11
11
  end
data/CHANGELOG.md CHANGED
@@ -2,6 +2,72 @@
2
2
 
3
3
  * TODO: Replace this bullet point with an actual description of a change.
4
4
 
5
+ ### 3.0.0 (1 April 2026)
6
+
7
+ Breaking changes: ([#73](https://github.com/hausgold/rimless/pull/73))
8
+
9
+ * Upgraded `karafka` from `~> 1.4` to `~> 2.5` — now powered by librdkafka
10
+ instead of ruby-kafka. Consumer groups are now shared (one for all topics
11
+ instead of one per topic). Batch fetching is always on; tune
12
+ `max_wait_time`/`max_messages` for latency vs throughput.
13
+ See `UPGRADING.md` for details.
14
+
15
+ * Upgraded `waterdrop` from `~> 1.4` to `~> 2.8` — all time-related config
16
+ values are now in milliseconds. The Rimless producer helpers (`Rimless.message`
17
+ etc.) remain unchanged.
18
+
19
+ * Upgraded `avro_turf` from `~> 0.11.0` to `~> 1.20`
20
+
21
+ * Switched from Sidekiq to ActiveJob for consumer job processing. The
22
+ `karafka-sidekiq-backend` gem is no longer used.
23
+
24
+ * Renamed constants (old → new):
25
+ - `Rimless::BaseConsumer` → `Rimless::Consumer::Base`
26
+ - `Rimless::ConsumerApp` → `Rimless::Consumer::App`
27
+ - `Rimless::ConsumerJob` → `Rimless::Consumer::Job`
28
+ - `Rimless::Karafka::AvroDeserializer` → `Rimless::Consumer::AvroDeserializer`
29
+
30
+ * Removed constants:
31
+ - `Rimless::Karafka::Base64Interchanger` (no longer needed)
32
+ - `Rimless::Karafka::PassthroughMapper` (mappers removed in Karafka 2)
33
+
34
+ * Anonymous consumer classes are no longer supported. Because Karafka is no
35
+ longer loaded within the ActiveJob worker process, consumer class names must
36
+ be serializable (via `constantize`). Rewrite anonymous consumers as named
37
+ classes. See `UPGRADING.md` for details.
38
+
39
+ * Each Kafka message in a batch is now individually marked as consumed after
40
+ being enqueued to ActiveJob (`mark_as_consumed`). This may differ from
41
+ previous `karafka-sidekiq-backend` behavior depending on your Karafka
42
+ offset management configuration. See `UPGRADING.md` for details.
43
+
44
+ * `KAFKA_BROKERS` format changed — protocol prefix (`kafka://`) is no longer
45
+ required. Use plain `host:port` CSV (e.g. `your.domain:9092,host:port`).
46
+ The old `kafka://` format is still accepted for backwards compatibility.
47
+
48
+ * Consumer boot flow changed:
49
+ - Remove `.boot!` from the end of `Rimless.consumer.topics(...)` in
50
+ `karafka.rb`
51
+ - Remove `WaterDrop.setup` and `WaterDrop::Instrumentation::LoggerListener`
52
+ subscriptions from `karafka.rb`
53
+
54
+ New configuration options:
55
+
56
+ * `config.job_bridge_class` — custom job bridge for Kafka → ActiveJob
57
+ * `config.consumer_job_class` — custom consumer job class
58
+ * `config.consumer_logger_listener` — customize Karafka logging listener
59
+ * `config.avro_deserializer_class` — custom Apache Avro deserializer
60
+ * `config.avro_configure` — fully customize the `AvroTurf::Messaging` instance
61
+ * `config.producer_configure` — fully customize the `WaterDrop::Producer` instance
62
+ * `config.consumer_configure` — fully customize the `Karafka::App` instance
63
+
64
+ Testing changes:
65
+
66
+ * Replace `#karafka_consumer_for` with `#kafka_consumer_for` in specs
67
+ * Replace `#publish_for_karafka` with `karafka.produce` in specs
68
+
69
+ See [`UPGRADING.md`](./UPGRADING.md) for a complete migration guide.
70
+
5
71
  ### 2.9.0 (18 February 2026)
6
72
 
7
73
  * Dropped 3rd-level gem dependencies which are not directly used
data/Gemfile CHANGED
@@ -13,7 +13,6 @@ gem 'bundler', '>= 2.6', '< 5'
13
13
  gem 'countless', '~> 2.2'
14
14
  gem 'factory_bot', '~> 6.2'
15
15
  gem 'guard-rspec', '~> 4.7'
16
- gem 'railties', '>= 8.0'
17
16
  gem 'rake', '~> 13.0'
18
17
  gem 'redcarpet', '~> 3.5'
19
18
  gem 'rspec', '~> 3.12'
data/README.md CHANGED
@@ -6,13 +6,15 @@
6
6
  [![Test Ratio](https://automate-api.hausgold.de/v1/coverage_reports/rimless/ratio.svg)](https://knowledge.hausgold.de/coverage)
7
7
  [![API docs](https://automate-api.hausgold.de/v1/coverage_reports/rimless/documentation.svg)](https://www.rubydoc.info/gems/rimless)
8
8
 
9
- This project is dedicated to ship a ready to use [Apache
9
+ This project is dedicated to shipping a ready-to-use [Apache
10
10
  Kafka](https://kafka.apache.org/) / [Confluent Schema
11
11
  Registry](https://docs.confluent.io/current/schema-registry/index.html) /
12
- [Apache Avro](https://avro.apache.org/) message producing toolset by making use
13
- of the [WaterDrop](https://rubygems.org/gems/waterdrop) and
12
+ [Apache Avro](https://avro.apache.org/) message streaming toolset by making use
13
+ of the [WaterDrop](https://rubygems.org/gems/waterdrop),
14
+ [Karafka](https://rubygems.org/gems/karafka) and
14
15
  [AvroTurf](https://rubygems.org/gems/avro_turf) gems. It comes as an
15
- opinionated framework which sets up solid conventions for producing messages.
16
+ opinionated framework that sets up solid conventions for producing and
17
+ consuming messages.
16
18
 
17
19
  - [Installation](#installation)
18
20
  - [Usage](#usage)
@@ -60,7 +62,7 @@ $ gem install rimless
60
62
 
61
63
  ### Configuration
62
64
 
63
- You can configure the rimless gem via an Rails initializer, by environment
65
+ You can configure the rimless gem via a Rails initializer, by environment
64
66
  variables or on demand. Here we show a common Rails initializer example:
65
67
 
66
68
  ```ruby
@@ -82,33 +84,42 @@ Rimless.configure do |conf|
82
84
 
83
85
  # The list of Apache Kafka brokers for cluster discovery,
84
86
  # set to HAUSGOLD defaults when not set
85
- conf.kafka_brokers = 'kafka://your.domain:9092,kafka..'
87
+ conf.kafka_brokers = 'kafka://your.domain:9092,kafka..' # old format
88
+ conf.kafka_brokers = 'your.domain:9092,host:port..' # new format
86
89
 
87
90
  # The Confluent Schema Registry API URL,
88
91
  # set to HAUSGOLD defaults when not set
89
92
  conf.schema_registry_url = 'http://your.schema-registry.local'
90
93
 
91
- # The Sidekiq job queue to use for consuming jobs
94
+ # The ActiveJob queue to use for consuming jobs
92
95
  config.consumer_job_queue = 'default'
93
96
  end
94
97
  ```
95
98
 
96
- The rimless gem comes with sensitive defaults as you can see. For most users an
97
- extra configuration is not needed.
99
+ The rimless gem comes with sensible defaults as you can see. For most users an
100
+ extra configuration is not needed. For more details and all available
101
+ configurations, check the
102
+ [`lib/rimless/configuration.rb`](lib/rimless/configuration.rb) file.
98
103
 
99
104
  #### Available environment variables
100
105
 
101
- The rimless gem can be configured hardly with its configuration code block like
106
+ The rimless gem can also be configured with its configuration code block as
102
107
  shown before. Respecting the [twelve-factor app](https://12factor.net/)
103
108
  concerns, the gem allows you to set almost all configurations (just the
104
109
  relevant ones for runtime) via environment variables. Here comes a list of
105
110
  available configuration options:
106
111
 
107
- * **KAFKA_ENV**: The application environment. Falls back to `Rails.env` when available.
108
- * **KAFKA_CLIENT_ID**: The Apache Kafka client identifier, falls back the the local application name.
109
- * **KAFKA_BROKERS**: A comma separated list of Apache Kafka brokers for cluster discovery (Plaintext, no-auth/no-SSL only for now) (eg. `kafka://your.domain:9092,kafka..`)
110
- * **KAFKA_SCHEMA_REGISTRY_URL**: The Confluent Schema Registry API URL to use for schema registrations.
111
- * **KAFKA_SIDEKIQ_JOB_QUEUE**: The Sidekiq job queue to use for consuming jobs. Falls back to `default`.
112
+ * **KAFKA_ENV**: The application environment. Falls back to `Rails.env` when
113
+ available.
114
+ * **KAFKA_CLIENT_ID**: The Apache Kafka client identifier, falls back to the
115
+ local application name.
116
+ * **KAFKA_BROKERS**: A comma-separated list of Apache Kafka brokers for cluster
117
+ discovery (Plaintext, no-auth/no-SSL by default) (eg.
118
+ `your.domain:9092,host:port..`)
119
+ * **KAFKA_SCHEMA_REGISTRY_URL**: The Confluent Schema Registry API URL to use
120
+ for schema registrations.
121
+ * **KAFKA_JOB_QUEUE**: The ActiveJob queue to use for consuming jobs.
122
+ Falls back to `default`. (falls back to `KAFKA_SIDEKIQ_JOB_QUEUE`)
112
123
 
113
124
  ### Conventions
114
125
 
@@ -158,13 +169,13 @@ templates](https://ruby-doc.org/stdlib-2.6.2/libdoc/erb/rdoc/ERB.html) and
158
169
  painless JSON validation of them.
159
170
 
160
171
  First things first, by convention the rimless gem looks for Apache Avro schema
161
- ERB templates on the `$(pwd)/config/avro_schemas` directory. Nothing special
172
+ ERB templates in the `$(pwd)/config/avro_schemas` directory. Nothing special
162
173
  from the Rails perspective. You can also reconfigure the file locations, just
163
174
  [see the configuration
164
175
  block](https://github.com/hausgold/rimless/blob/master/lib/rimless/configuration.rb#L36).
165
176
 
166
177
  Each schema template MUST end with the `.avsc.erb` extension to be picked up,
167
- even in recursive directory structures. You can make use of the ERB templating
178
+ even in recursive directory structures. You can make use of the ERB templating
168
179
  or not, but rimless just looks for these templates. When it comes to
169
180
  structuring the Avro Schemas it is important that the file path reflects the
170
181
  embedded schema namespace correctly. So when `$(pwd)/config/avro_schemas` is our
@@ -178,7 +189,7 @@ The corresponding Avro Schema template is located at
178
189
  be fancy. The automatic schema compiler picks up the dynamically/runtime set
179
190
  namespace from the schema definition and converts it to its respective
180
191
  directory structure. So when you boot your application container/instance
181
- inside your *canary* environment, the schemas/messages should reflect this so
192
+ inside your *canary* environment, the schemas/messages should reflect this so
182
193
  they do not mix with other environments.
183
194
 
184
195
  Example time. **$(pwd)/config/avro_schemas/identity_api/user_v1.avsc.erb**:
@@ -237,7 +248,7 @@ The compiled Avro Schemas are written to the
237
248
  `$(pwd)/config/avro_schemas/compiled/` directory by default. You can
238
249
  [reconfigure the
239
250
  location](https://github.com/hausgold/rimless/blob/master/lib/rimless/configuration.rb#L44)
240
- if needed. For VCS systems like Git it is useful to create an relative ignore
251
+ if needed. For VCS systems like Git it is useful to create a relative ignore
241
252
  list at `$(pwd)/config/avro_schemas/.gitignore` with the following contents:
242
253
 
243
254
  ```gitignore
@@ -248,8 +259,8 @@ compiled/
248
259
 
249
260
  Under the hood the rimless gem makes use of the [WaterDrop
250
261
  gem](https://rubygems.org/gems/waterdrop) to send messages to the Apache Kafka
251
- cluster. But with the addition to send Apache Avro encoded messages with a
252
- single call. Here comes some examples how to use it:
262
+ cluster, but with the added ability to send Apache Avro encoded messages with a
263
+ single call. Here are some examples of how to use it:
253
264
 
254
265
  ```ruby
255
266
  metadata = { hobbies: %w(dancing singing sports) }
@@ -279,7 +290,7 @@ Rimless.raw_message(data: encoded, topic: :users)
279
290
 
280
291
  # In case you want to send messages to a non-local application topic you can
281
292
  # specify the application, too. This allows you to send a message to the
282
- # +<ENV>.address-api.addresses+ from you local identity-api.
293
+ # +<ENV>.address-api.addresses+ from your local identity-api.
283
294
  Rimless.raw_message(data: encoded, topic: { name: :users, app: 'address-api' })
284
295
  # Also works with the Apache Avro encoding variant
285
296
  Rimless.message(data: user, schema: :user_v1,
@@ -295,8 +306,8 @@ Rimless.async_raw_message(data: encoded, topic: :users)
295
306
  The rimless gem makes it super easy to build consumer logic right into your
296
307
  (Rails, standalone) application by utilizing the [Karafka
297
308
  framework](https://github.com/karafka/karafka) under the hood. When you have
298
- the rimless gem already installed you are ready to rumble to setup your
299
- application to consume Apache Kafka messages. Just run the `$ rake
309
+ the rimless gem already installed, you are ready to set up your application to
310
+ consume Apache Kafka messages. Just run the `$ rake
300
311
  rimless:install` and all the consuming setup is done for you.
301
312
 
302
313
  Afterwards you find the `karafka.rb` file at the root of your project together
@@ -312,7 +323,7 @@ architecture looks like this:
312
323
  v
313
324
  +-----------------------------+
314
325
  | Karafka/Rimless Consumer | +--------------------------------------+
315
- | Shares a single consumer |--->| Sidekiq |
326
+ | Shares a single consumer |--->| ActiveJob |
316
327
  | group, multiple processes | | Runs the consumer class (children |
317
328
  +-----------------------------+ | of Rimless::BaseConsumer) for each |
318
329
  | message (Rimless::ConsumerJob), |
@@ -321,15 +332,15 @@ architecture looks like this:
321
332
  ```
322
333
 
323
334
  This architecture allows the consumer process to run mostly non-blocking and
324
- the messages can be processed concurrently via Sidekiq. (including the error
335
+ the messages can be processed concurrently via ActiveJob. (including the error
325
336
  handling and retrying)
326
337
 
327
338
  #### Routing messages to consumers
328
339
 
329
340
  The `karafka.rb` file at the root of your project is dedicated to configure the
330
341
  consumer process, including the routing table. The routing is as easy as it
331
- gets by following this pattern: `topic => consumer`. Here comes a the full
332
- examples:
342
+ gets by following this pattern: `topic => consumer`. Here is the full
343
+ example:
333
344
 
334
345
  ```ruby
335
346
  # Setup the topic-consumer routing table and boot the consumer application
@@ -338,7 +349,7 @@ Rimless.consumer.topics(
338
349
  ).boot!
339
350
  ```
340
351
 
341
- The key side of the hash is anything which is understood by the `Rimless.topic`
352
+ The key side of the hash is anything that is understood by the `Rimless.topic`
342
353
  method. With one addition: you can change `:name` to `:names` and pass an array
343
354
  of strings or symbols to listen to multiple application topics with a single
344
355
  configuration line.
@@ -360,9 +371,9 @@ Rimless.consumer.topics(
360
371
  #### Consuming event messages
361
372
 
362
373
  By convention it makes sense to produce messages with various event types on a
363
- single Apache Kafka topic. This is fine, they just must follow a single
364
- constrain: each message must contain an `event`-named field at the Apache Avro
365
- schema with a dedicated name. This allow to structure data at Kafka like this:
374
+ single Apache Kafka topic. This is fine; they just must follow a single
375
+ constraint: each message must contain an `event`-named field in the Apache Avro
376
+ schema with a dedicated name. This allows structuring data in Kafka like this:
366
377
 
367
378
  ```
368
379
  Topic: production.users-api.users
@@ -370,7 +381,7 @@ Events: user_created, user_updated, user_deleted
370
381
  ```
371
382
 
372
383
  While respecting this convention your consumer classes will be super clean. See
373
- the following example: (we keep the users api example)
384
+ the following example: (we keep the Users API example)
374
385
 
375
386
  ```ruby
376
387
  class UserApiConsumer < ApplicationConsumer
@@ -385,7 +396,7 @@ schema fields of it, except the event field. The messages will be automatically
385
396
  decoded with the help of the schema registry. All hashes/arrays ship deeply
386
397
  symbolized keys for easy access.
387
398
 
388
- **Heads up!** All messages with events which are not reflected by a method will
399
+ **Heads up!** All messages with events that are not reflected by a method will
389
400
  just be ignored.
390
401
 
391
402
  See the automatically generated spec (`spec/consumers/custom_consumer_spec.rb`)
@@ -408,20 +419,11 @@ $ rake rimless:routes
408
419
  #### Starting the consumer process(es)
409
420
 
410
421
  From system integration perspective you just need to start the consumer
411
- processes and Sidekiq to get the thing going. Rimless allows you to start the
422
+ processes and ActiveJob to get the thing going. Rimless allows you to start the
412
423
  consumer with `$ rake rimless:consumer` or you can just use the [Karafka
413
424
  binary](https://github.com/karafka/karafka/wiki/Fetching-messages) to start the
414
425
  consumer (`$ bundle exec karafka server`). Both work identically.
415
426
 
416
- When running inside a Rails application the consumer application initialization
417
- is automatically done for Sidekiq. Otherwise you need to initialize the
418
- consumer application manually with:
419
-
420
- ```ruby
421
- # Manual consumer application initialization
422
- Sidekiq.configure_server { Rimless.consumer.initialize! }
423
- ```
424
-
425
427
  ### Encoding/Decoding messages
426
428
 
427
429
  By convention we focus on the [Apache Avro](https://avro.apache.org/) data
@@ -430,14 +432,14 @@ gem and the rimless gem adds some neat helpers on top of it. Here are a few
430
432
  examples to show how rimless can be used to encode/decode Apache Avro data:
431
433
 
432
434
  ```ruby
433
- # Encode a data structure (no matter of symbolized, or stringified keys, or
435
+ # Encode a data structure (regardless of symbolized or stringified keys, or
434
436
  # non-simple types) to Apache Avro format
435
437
  encoded = Rimless.encode(user, schema: 'user_v1')
436
438
 
437
439
  # Works the same for symbolized schema names
438
440
  encoded = Rimless.encode(user, schema: :user_v1)
439
441
 
440
- # Also supports the resolution of deep relative schemes
442
+ # Also supports the resolution of deep relative schemas
441
443
  # (+.user.address+ becomes +<ENV>.<APP>.user.address+)
442
444
  encoded = Rimless.encode(user.address, schema: '.user.address')
443
445
 
@@ -448,15 +450,15 @@ decoded = Rimless.decode('your-avro-binary-data-here')
448
450
 
449
451
  #### Handling of schemaless deep blobs
450
452
 
451
- Apache Avro is by design a strict, type casted format which does not allow
453
+ Apache Avro is by design a strict, type-cast format that does not allow
452
454
  undefined mix and matching of deep structures. This is fine because it forces
453
455
  the producer to think twice about the schema definition. But sometimes there is
454
456
  unstructured data inside of entities. Think of a metadata hash on a user entity
455
- were the user (eg. a frontend client) just can add whatever comes to his mind
456
- for later processing. Its not searchable, its never touched by the backend, but
457
- its present.
457
+ where the user (e.g. a frontend client) can just add whatever comes to mind
458
+ for later processing. It's not searchable, it's never touched by the backend,
459
+ but it's present.
458
460
 
459
- That's a case we're experienced and kind of solved on the rimless gem. You can
461
+ That's a case we've experienced and kind of solved in the rimless gem. You can
460
462
  make use of the `Rimless.avro_schemaless_h` method to [sparsify the data
461
463
  recursively](https://github.com/simplymeasured/sparsify). Say you have the
462
464
  following metadata hash:
@@ -475,7 +477,7 @@ metadata = {
475
477
  ```
476
478
 
477
479
  It's messy, by design. From the Apache Avro perspective you just can define a
478
- map. The map keys are assumed to be strings - and the most hitting value data
480
+ map. The map keys are assumed to be strings and the most fitting value data
479
481
  type is a string, too. That's where hash sparsification comes in. The resulting
480
482
  metadata hash looks like this and can be encoded by Apache Avro:
481
483
 
@@ -492,18 +494,18 @@ Rimless.avro_schemaless_h(metadata)
492
494
  ```
493
495
 
494
496
  With the help of the [sparsify gem](https://rubygems.org/gems/sparsify) you can
495
- also revert this to its original form. But with the loss of data type
496
- correctness. Another approach can be used for these kind of scenarios: encoding
497
+ also revert this to its original form, but with the loss of data type
498
+ correctness. Another approach can be used for these kinds of scenarios: encoding
497
499
  the schemaless data with JSON and just set the metadata field on the Apache
498
500
  Avro schema to be a string. Choice is yours.
499
501
 
500
502
  ### Writing tests for your messages
501
503
 
502
- Producing messages is a bliss with the rimless gem, but producing code needs to
504
+ Producing messages is a breeze with the rimless gem, but producing code needs to
503
505
  be tested as well. That's why the gem ships some RSpec helpers and matchers for
504
506
  this purpose. A common situation is also handled by the RSpec extension: on the
505
- test environment (eg. a continuous integration service) its not likely to have
506
- a Apache Kafka/Confluent Schema Registry cluster available. That's why actual
507
+ test environment (e.g. a continuous integration service) it's not likely to have
508
+ an Apache Kafka/Confluent Schema Registry cluster available. That's why actual
507
509
  calls to Kafka/Schema Registry are mocked away.
508
510
 
509
511
  First of all, just add `require 'rimless/rspec'` to your `spec_helper.rb` or
@@ -525,8 +527,8 @@ end
525
527
 
526
528
  Nothing special, not really fancy. A more complex situation occurs when you
527
529
  separate your Kafka message producing logic inside an asynchronous job (eg.
528
- Sidekiq or ActiveJob). Therefore is the `have_sent_kafka_message` matcher
529
- available. Example time:
530
+ ActiveJob). The `have_sent_kafka_message` matcher is available for
531
+ this purpose. Example time:
530
532
 
531
533
  ```ruby
532
534
  describe 'message producer job' do
@@ -559,7 +561,7 @@ describe 'message producer job' do
559
561
  expect { action }.to \
560
562
  have_sent_kafka_message.with(key: String, topic: anything)
561
563
  # mind the order --^
562
- # its a argument list validation, all keys must be named
564
+ # it's an argument list validation, all keys must be named
563
565
  end
564
566
 
565
567
  it 'sends the correct user data' do
@@ -571,14 +573,14 @@ describe 'message producer job' do
571
573
  expect { nil }.not_to have_sent_kafka_message
572
574
  end
573
575
 
574
- it 'allows complex expactations' do
576
+ it 'allows complex expectations' do
575
577
  expect { action; action }.to \
576
578
  have_sent_kafka_message('test.identity_api.user_v1')
577
579
  .with(key: user.id, topic: 'test.identity-api.users').twice
578
580
  .with_data(firstname: 'John', lastname: 'Doe').twice
579
581
  end
580
582
 
581
- it 'allows to capture messages to check them in detail' do
583
+ it 'allows capturing messages to check them in detail' do
582
584
  (capture_kafka_messages { action }).tap do |messages|
583
585
  expect(messages.first[:data]).to \
584
586
  match(a_hash_including('entity' => a_hash_including('items' => items)))
data/Rakefile CHANGED
@@ -15,10 +15,19 @@ Countless.configure do |config|
15
15
  pattern: %r{/lib(/rimless)?/[^/]+\.rb$} },
16
16
  { name: 'Top-levels specs', test: true, dir: 'spec',
17
17
  pattern: %r{/spec(/rimless)?/[^/]+_spec\.rb$} },
18
- { name: 'RSpec matchers', pattern: 'lib/rimless/rspec/**/*.rb' },
19
- { name: 'RSpec matchers specs', test: true,
18
+ { name: 'Initializers', pattern: 'lib/rimless/initializers/**/*.rb' },
19
+ { name: 'Compatibilities', pattern: 'lib/rimless/compatibility/**/*.rb' },
20
+ { name: 'Compatibilities specs', test: true,
21
+ pattern: 'spec/rimless/compatibility/**/*_spec.rb' },
22
+ { name: 'Consumer', pattern: 'lib/rimless/consumer/**/*.rb' },
23
+ { name: 'Consumer specs', test: true,
24
+ pattern: 'spec/rimless/consumer/**/*_spec.rb' },
25
+ { name: 'Extensions', pattern: 'lib/rimless/extensions/**/*.rb' },
26
+ { name: 'Extensions specs', test: true,
27
+ pattern: 'spec/rimless/extensions/**/*_spec.rb' },
28
+ { name: 'RSpec extensions', pattern: 'lib/rimless/rspec/**/*.rb' },
29
+ { name: 'RSpec extensions specs', test: true,
20
30
  pattern: 'spec/rimless/rspec/**/*_spec.rb' },
21
- { name: 'Rake Tasks', pattern: 'lib/rimless/tasks/**/*' },
22
- { name: 'Karafka Extensions', pattern: 'lib/rimless/karafka/**/*.rb' }
31
+ { name: 'Rake Tasks', pattern: 'lib/rimless/tasks/**/*' }
23
32
  ]
24
33
  end