deimos-ruby 1.16.0 → 1.16.3

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/README.md +17 -0
  4. data/lib/deimos/active_record_producer.rb +7 -0
  5. data/lib/deimos/schema_class/base.rb +1 -1
  6. data/lib/deimos/schema_class/enum.rb +5 -0
  7. data/lib/deimos/schema_class/record.rb +7 -1
  8. data/lib/deimos/version.rb +1 -1
  9. data/lib/generators/deimos/schema_class/templates/schema_record.rb.tt +13 -5
  10. data/lib/generators/deimos/schema_class_generator.rb +40 -22
  11. data/regenerate_test_schema_classes.rb +68 -0
  12. data/spec/active_record_producer_spec.rb +24 -0
  13. data/spec/generators/schema_class/my_schema_spec.rb +16 -0
  14. data/spec/generators/schema_class/my_schema_with_circular_reference_spec.rb +1 -1
  15. data/spec/generators/schema_class/my_schema_with_complex_types_spec.rb +32 -24
  16. data/spec/producer_spec.rb +11 -11
  17. data/spec/schemas/{generated.rb → my_namespace/generated.rb} +28 -32
  18. data/spec/schemas/{my_nested_schema.rb → my_namespace/my_nested_schema.rb} +23 -16
  19. data/spec/schemas/{my_schema.rb → my_namespace/my_schema.rb} +12 -5
  20. data/spec/schemas/my_namespace/my_schema_compound_key.rb +41 -0
  21. data/spec/schemas/my_namespace/my_schema_id_key.rb +36 -0
  22. data/spec/schemas/{my_schema_key.rb → my_namespace/my_schema_key.rb} +3 -3
  23. data/spec/schemas/my_namespace/my_schema_with_boolean.rb +41 -0
  24. data/spec/schemas/{my_schema_with_circular_reference.rb → my_namespace/my_schema_with_circular_reference.rb} +15 -10
  25. data/spec/schemas/{my_schema_with_complex_type.rb → my_namespace/my_schema_with_complex_type.rb} +34 -49
  26. data/spec/schemas/my_namespace/my_schema_with_date_time.rb +56 -0
  27. data/spec/schemas/my_namespace/my_schema_with_id.rb +51 -0
  28. data/spec/schemas/my_namespace/my_schema_with_unique_id.rb +56 -0
  29. data/spec/schemas/my_namespace/wibble.rb +76 -0
  30. data/spec/schemas/my_namespace/widget.rb +56 -0
  31. data/spec/schemas/my_namespace/widget_the_second.rb +56 -0
  32. data/spec/schemas/request/create_topic.rb +36 -0
  33. data/spec/schemas/request/index.rb +36 -0
  34. data/spec/schemas/request/update_request.rb +36 -0
  35. data/spec/schemas/response/create_topic.rb +36 -0
  36. data/spec/schemas/response/index.rb +36 -0
  37. data/spec/schemas/response/update_response.rb +36 -0
  38. data/spec/snapshots/consumers-no-nest.snap +93 -86
  39. data/spec/snapshots/consumers.snap +94 -87
  40. data/spec/snapshots/consumers_and_producers-no-nest.snap +108 -87
  41. data/spec/snapshots/consumers_and_producers.snap +109 -88
  42. data/spec/snapshots/consumers_circular-no-nest.snap +93 -86
  43. data/spec/snapshots/consumers_circular.snap +94 -87
  44. data/spec/snapshots/consumers_complex_types-no-nest.snap +93 -86
  45. data/spec/snapshots/consumers_complex_types.snap +94 -87
  46. data/spec/snapshots/consumers_nested-no-nest.snap +93 -86
  47. data/spec/snapshots/consumers_nested.snap +94 -87
  48. data/spec/snapshots/namespace_folders.snap +111 -90
  49. data/spec/snapshots/producers_with_key-no-nest.snap +94 -87
  50. data/spec/snapshots/producers_with_key.snap +95 -88
  51. data/spec/spec_helper.rb +2 -1
  52. metadata +48 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f1e9c8dc0d42ccbe5d9e8913532647e9b295349861b9383583ca2575c501793
4
- data.tar.gz: 4b77ed26c85469b0cb54c0dabdd17695a383210c6d00f3415a70ea17d35c0669
3
+ metadata.gz: 6ee238a0bcc822c984f19d5a58d1bea52025407d931654371831b0104fcb5aed
4
+ data.tar.gz: 5b767073027dae54910c69be504ac2da023d540557ef592417f1f60254f9e3f3
5
5
  SHA512:
6
- metadata.gz: 531da2cb0ff866c4c00f69c9e9047f516002c519004021530f589eaacd12f3e245f3b58d018350b5eb2454413331f45c693de3b7071667031be76ea10827bbc0
7
- data.tar.gz: dd39086104accf36bdcfd93a975cf58ef29526dd55cfadeae85fce4a6dbf21d77a242e92e7ca5976a7015d54eb339cd9ca5bd3de63368b54f87c5a38c5c0a566
6
+ metadata.gz: 904066c010866aaa6ca1173bbdf4e4044c578ac28df8a0ebcf846c25c73cd484fbeb15dea827c3b64935a8f7588f4a62b65d1bdf6f28604d0f1e588cdb8cb15a
7
+ data.tar.gz: 3cec3d2ae05d855fb9835252646b6cdef16034f600b0c1b7ed169fc8b7969bb0d6a9847fd5b35092e29ca910daa91cad6b3d838425a3b577dc484d7937af1339
data/CHANGELOG.md CHANGED
@@ -7,7 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
- # 1.16.0 - 2022-08-03
10
+ # 1.16.3 - 2022-09-08
11
+
12
+ - Add the `tombstone` method to schema classes.
13
+
14
+ # 1.16.2 - 2022-09-07
15
+
16
+ - Added support of post_process method in ActiveRecordProducer
17
+
18
+ # 1.16.1 - 2022-08-03
11
19
 
12
20
  - Fix issues with `enum` schema classes (e.g. equality not working, `to_s` not working)
13
21
  - Changed assumption in the base schema class that it was a record (e.g. defining `to_h` instead of `as_json`). Moved record functionality to the record base class.
data/README.md CHANGED
@@ -785,6 +785,21 @@ have one process running at a time. If a particular poll takes longer than
785
785
  the poll interval (i.e. interval is set at 1 minute but it takes 75 seconds)
786
786
  the next poll will begin immediately following the first one completing.
787
787
 
788
+ To Post-Process records that are sent to Kafka:
789
+
790
+ You need to define one additional method in your producer class to post-process the messages sent to Kafka.
791
+
792
+ ```ruby
793
+ class MyProducer < Deimos::ActiveRecordProducer
794
+ ...
795
+ def post_process(batch)
796
+ # If you need to do some extra actions with
797
+ # the collection of elements you just sent to Kafka
798
+ # write some code here
799
+ end
800
+ end
801
+ ```
802
+
788
803
  ## Running consumers
789
804
 
790
805
  Deimos includes a rake task. Once it's in your gemfile, just run
@@ -824,6 +839,8 @@ One additional configuration option indicates whether nested records should be g
824
839
 
825
840
  config.schema.nest_child_schemas = false # Flatten all classes into one directory
826
841
 
842
+ You can generate a tombstone message (with only a key and no value) by calling the `YourSchemaClass.tombstone(key)` method. If you're using a `:field` key config, you can pass in just the key scalar value. If using a key schema, you can pass it in as a hash or as another schema class.
843
+
827
844
  ### Consumer
828
845
 
829
846
  The consumer interface uses the `decode_message` method to turn JSON hash into the Schemas
@@ -44,6 +44,7 @@ module Deimos
44
44
  generate_payload(attrs, record).with_indifferent_access
45
45
  end
46
46
  self.publish_list(messages, force_send: force_send)
47
+ self.post_process(records)
47
48
  end
48
49
 
49
50
  # Generate the payload, given a list of attributes or a record..
@@ -85,6 +86,12 @@ module Deimos
85
86
  time_to
86
87
  )
87
88
  end
89
+
90
+ # Post process records after publishing
91
+ # @param records [Array<ActiveRecord::Base>]
92
+ def post_process(_records)
93
+ end
94
+
88
95
  end
89
96
  end
90
97
  end
@@ -34,7 +34,7 @@ module Deimos
34
34
  end
35
35
 
36
36
  # :nodoc:
37
- def to_s
37
+ def inspect
38
38
  klass = self.class
39
39
  "#{klass}(#{self.as_json})"
40
40
  end
@@ -15,6 +15,11 @@ module Deimos
15
15
  other.is_a?(self.class) ? other.value == @value : other == @value
16
16
  end
17
17
 
18
+ # @return [String]
19
+ def to_s
20
+ @value.to_s
21
+ end
22
+
18
23
  # @param value [String]
19
24
  def initialize(value)
20
25
  @value = value
@@ -8,10 +8,16 @@ module Deimos
8
8
  # Base Class of Record Classes generated from Avro.
9
9
  class Record < Base
10
10
 
11
+ attr_accessor :tombstone_key
12
+
11
13
  # Converts the object attributes to a hash which can be used for Kafka
12
14
  # @return [Hash] the payload as a hash.
13
15
  def to_h
14
- self.as_json
16
+ if self.tombstone_key
17
+ { payload_key: self.tombstone_key&.as_json }
18
+ else
19
+ self.as_json
20
+ end
15
21
  end
16
22
 
17
23
  # Merge a hash or an identical schema object with this one and return a new object.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Deimos
4
- VERSION = '1.16.0'
4
+ VERSION = '1.16.3'
5
5
  end
@@ -20,7 +20,7 @@
20
20
  <%- if @field_assignments.select{ |h| !h[:is_schema_class] }.any? -%>
21
21
  ### Attribute Accessors ###
22
22
  <%- @field_assignments.select{ |h| !h[:is_schema_class] }.each do |method_definition| -%>
23
- # @param <%= method_definition[:method_argument] %> [<%= method_definition[:deimos_type] %>]
23
+ # @return [<%= method_definition[:deimos_type] %>]
24
24
  attr_accessor :<%= method_definition[:field].name %>
25
25
  <%- end -%>
26
26
 
@@ -28,14 +28,14 @@
28
28
  <%- if @field_assignments.select{ |h| h[:is_schema_class] }.any? -%>
29
29
  ### Attribute Writers ###
30
30
  <%- @field_assignments.select{ |h| h[:is_schema_class] }.each do |method_definition| -%>
31
- # @param <%= method_definition[:method_argument] %> [<%= method_definition[:deimos_type] %>]
31
+ # @return [<%= method_definition[:deimos_type] %>]
32
32
  def <%= method_definition[:field].name %>=(<%= method_definition[:method_argument] %>)
33
33
  <%- if method_definition[:field_type] == :array -%>
34
- @<%= method_definition[:field].name %> = values.map do |value|
34
+ @<%= method_definition[:field].name %> = values&.map do |value|
35
35
  <%= method_definition[:field_initialization] %>
36
36
  end
37
37
  <%- elsif method_definition[:field_type] == :map -%>
38
- @<%= method_definition[:field].name %> = values.transform_values do |value|
38
+ @<%= method_definition[:field].name %> = values&.transform_values do |value|
39
39
  <%= method_definition[:field_initialization] %>
40
40
  end
41
41
  <%- else -%>
@@ -62,7 +62,15 @@
62
62
  def namespace
63
63
  '<%= @current_schema.namespace %>'
64
64
  end
65
-
65
+ <%- if @tombstone_assignment %>
66
+ def self.tombstone(key)
67
+ record = self.new
68
+ <%- if @tombstone_assignment.present? -%>
69
+ <%= @tombstone_assignment %>
70
+ <%- end -%>
71
+ record
72
+ end
73
+ <%- end %>
66
74
  # @override
67
75
  def as_json(_opts={})
68
76
  {
@@ -41,16 +41,16 @@ module Deimos
41
41
  # Deimos Consumer or Producer Configuration object
42
42
  # @param schema_name [String]
43
43
  # @param namespace [String]
44
- # @param key_schema_name [String,nil]
45
- def generate_classes(schema_name, namespace, key_schema_name)
44
+ # @param key_config [Hash,nil]
45
+ def generate_classes(schema_name, namespace, key_config)
46
46
  schema_base = Deimos.schema_backend(schema: schema_name, namespace: namespace)
47
47
  schema_base.load_schema
48
- if key_schema_name.present?
49
- key_schema_base = Deimos.schema_backend(schema: key_schema_name, namespace: namespace)
48
+ if key_config&.dig(:schema)
49
+ key_schema_base = Deimos.schema_backend(schema: key_config[:schema], namespace: namespace)
50
50
  key_schema_base.load_schema
51
- generate_class_from_schema_base(key_schema_base)
51
+ generate_class_from_schema_base(key_schema_base, key_config: nil)
52
52
  end
53
- generate_class_from_schema_base(schema_base, key_schema_base: key_schema_base)
53
+ generate_class_from_schema_base(schema_base, key_config: key_config)
54
54
  end
55
55
 
56
56
  # @param schema [Avro::Schema::NamedSchema]
@@ -83,8 +83,8 @@ module Deimos
83
83
  end
84
84
 
85
85
  # @param schema_base [Deimos::SchemaBackends::Base]
86
- # @param key_schema_base[Avro::Schema::NamedSchema]
87
- def generate_class_from_schema_base(schema_base, key_schema_base: nil)
86
+ # @param key_config [Hash,nil]
87
+ def generate_class_from_schema_base(schema_base, key_config: nil)
88
88
  @discovered_schemas = Set.new
89
89
  @sub_schema_templates = []
90
90
  schemas = collect_all_schemas(schema_base.schema_store.schemas.values)
@@ -93,11 +93,11 @@ module Deimos
93
93
  sub_schemas = schemas.reject { |s| s.name == schema_base.schema }.sort_by(&:name)
94
94
  if Deimos.config.schema.nest_child_schemas
95
95
  @sub_schema_templates = sub_schemas.map do |schema|
96
- _generate_class_template_from_schema(schema)
96
+ _generate_class_template_from_schema(schema, nil)
97
97
  end
98
- write_file(main_schema, key_schema_base)
98
+ write_file(main_schema, key_config)
99
99
  else
100
- write_file(main_schema, key_schema_base)
100
+ write_file(main_schema, key_config)
101
101
  sub_schemas.each do |schema|
102
102
  write_file(schema, nil)
103
103
  end
@@ -105,9 +105,9 @@ module Deimos
105
105
  end
106
106
 
107
107
  # @param schema [Avro::Schema::NamedSchema]
108
- # @param key_schema_base [Avro::Schema::NamedSchema, nil]
109
- def write_file(schema, key_schema_base)
110
- class_template = _generate_class_template_from_schema(schema, key_schema_base)
108
+ # @param key_schema_base [Hash]
109
+ def write_file(schema, key_config)
110
+ class_template = _generate_class_template_from_schema(schema, key_config)
111
111
  @modules = Utils::SchemaClass.modules_for(schema.namespace)
112
112
  @main_class_definition = class_template
113
113
 
@@ -154,7 +154,7 @@ module Deimos
154
154
  key_schema_name = config.key_config[:schema]
155
155
  found_schemas.add("#{namespace}.#{schema_name}")
156
156
  found_schemas.add("#{namespace}.#{key_schema_name}") if key_schema_name
157
- generate_classes(schema_name, namespace, key_schema_name)
157
+ generate_classes(schema_name, namespace, config.key_config)
158
158
  end
159
159
 
160
160
  Deimos.config.consumer_objects.each do |config|
@@ -163,7 +163,7 @@ module Deimos
163
163
  key_schema_name = config.key_config[:schema]
164
164
  found_schemas.add("#{namespace}.#{schema_name}")
165
165
  found_schemas.add("#{namespace}.#{key_schema_name}") if key_schema_name
166
- generate_classes(schema_name, namespace, key_schema_name)
166
+ generate_classes(schema_name, namespace, config.key_config)
167
167
  end
168
168
 
169
169
  generate_from_schema_files(found_schemas)
@@ -191,10 +191,10 @@ module Deimos
191
191
  end
192
192
 
193
193
  # @param schema[Avro::Schema::NamedSchema]
194
- # @param key_schema_base[Avro::Schema::NamedSchema]
194
+ # @param key_config[Hash,nil]
195
195
  # @return [String]
196
- def _generate_class_template_from_schema(schema, key_schema_base=nil)
197
- _set_instance_variables(schema, key_schema_base)
196
+ def _generate_class_template_from_schema(schema, key_config)
197
+ _set_instance_variables(schema, key_config)
198
198
 
199
199
  temp = schema.is_a?(Avro::Schema::RecordSchema) ? _record_class_template : _enum_class_template
200
200
  res = ERB.new(temp, nil, '-')
@@ -202,20 +202,38 @@ module Deimos
202
202
  end
203
203
 
204
204
  # @param schema[Avro::Schema::NamedSchema]
205
- # @param key_schema_base[Avro::Schema::NamedSchema]
206
- def _set_instance_variables(schema, key_schema_base=nil)
205
+ # @param key_config [Hash,nil]
206
+ def _set_instance_variables(schema, key_config)
207
207
  schema_is_record = schema.is_a?(Avro::Schema::RecordSchema)
208
208
  @current_schema = schema
209
209
  return unless schema_is_record
210
210
 
211
211
  @fields = fields(schema)
212
- if key_schema_base.present?
212
+ key_schema = nil
213
+ if key_config&.dig(:schema)
214
+ key_schema_base = Deimos.schema_backend(schema: key_config[:schema], namespace: schema.namespace)
213
215
  key_schema_base.load_schema
214
216
  key_schema = key_schema_base.schema_store.schemas.values.first
215
217
  @fields << Deimos::SchemaField.new('payload_key', key_schema, [], nil)
216
218
  end
217
219
  @initialization_definition = _initialization_definition
218
220
  @field_assignments = _field_assignments
221
+ @tombstone_assignment = _tombstone_assignment(key_config, key_schema)
222
+ end
223
+
224
+ def _tombstone_assignment(key_config, key_schema)
225
+ return nil unless key_config
226
+
227
+ if key_config[:plain]
228
+ "record.tombstone_key = key"
229
+ elsif key_config[:field]
230
+ "record.tombstone_key = key\n record.#{key_config[:field]} = key"
231
+ elsif key_schema
232
+ field_base_type = _field_type(key_schema)
233
+ "record.tombstone_key = #{field_base_type}.initialize_from_value(key)\n record.payload_key = key"
234
+ else
235
+ ''
236
+ end
219
237
  end
220
238
 
221
239
  # Defines the initialization method for Schema Records with one keyword argument per line
@@ -0,0 +1,68 @@
1
+ #! /usr/bin/env ruby
2
+ require 'action_controller/railtie'
3
+ require 'deimos'
4
+ require 'deimos/metrics/mock'
5
+ require 'deimos/tracing/mock'
6
+ # not sure why "require deimos/utils/schema_class" doesn't work
7
+ require_relative 'lib/deimos/utils/schema_class'
8
+
9
+ class DeimosApp < Rails::Application
10
+ end
11
+ DeimosApp.initialize!
12
+
13
+ class MyConsumer < Deimos::Consumer
14
+ def consume(payload, metadata); end
15
+ end
16
+
17
+ require_relative "./lib/generators/deimos/schema_class_generator"
18
+
19
+ Deimos.configure do |deimos_config|
20
+ deimos_config.schema.nest_child_schemas = true
21
+ deimos_config.schema.path = "spec/schemas"
22
+ deimos_config.schema.backend = :avro_validation
23
+ deimos_config.schema.generated_class_path = './spec/schemas'
24
+ deimos_config.schema.generate_namespace_folders = true
25
+ deimos_config.schema.nest_child_schemas = true
26
+
27
+ consumer do
28
+ class_name 'MyConsumer'
29
+ topic 'MyTopic'
30
+ schema 'Generated'
31
+ namespace 'com.my-namespace'
32
+ key_config field: :a_string
33
+ end
34
+
35
+ consumer do
36
+ class_name 'MyConsumer'
37
+ topic 'MyTopic'
38
+ schema 'MySchemaWithComplexTypes'
39
+ namespace 'com.my-namespace'
40
+ key_config field: :test_id
41
+ end
42
+
43
+ consumer do
44
+ class_name 'MyConsumer'
45
+ topic 'MyTopic'
46
+ schema 'MySchemaWithCircularReference'
47
+ namespace 'com.my-namespace'
48
+ key_config none: true
49
+ end
50
+
51
+ consumer do
52
+ class_name 'MyConsumer'
53
+ topic 'MyTopic'
54
+ schema 'MyNestedSchema'
55
+ namespace 'com.my-namespace'
56
+ key_config field: :test_id
57
+ end
58
+
59
+ producer do
60
+ class_name 'MyConsumer'
61
+ topic 'MyTopic'
62
+ schema 'MySchema'
63
+ namespace 'com.my-namespace'
64
+ key_config schema: 'MySchema_key'
65
+ end
66
+ end
67
+
68
+ Deimos::Generators::SchemaClassGenerator.new.generate
@@ -45,6 +45,24 @@ describe Deimos::ActiveRecordProducer do
45
45
  record_class Widget
46
46
  end
47
47
  stub_const('MyProducerWithUniqueID', producer_class)
48
+
49
+ producer_class = Class.new(Deimos::ActiveRecordProducer) do
50
+ schema 'MySchemaWithUniqueId'
51
+ namespace 'com.my-namespace'
52
+ topic 'my-topic-with-unique-id'
53
+ key_config field: :id
54
+ record_class Widget
55
+
56
+ # :nodoc:
57
+ def self.post_process(batch)
58
+ batch.each do |message|
59
+ message.test_id = 'post_processed'
60
+ message.save!
61
+ end
62
+ end
63
+ end
64
+
65
+ stub_const('MyProducerWithPostProcess', producer_class)
48
66
  end
49
67
 
50
68
  describe 'produce' do
@@ -85,6 +103,12 @@ describe Deimos::ActiveRecordProducer do
85
103
  )
86
104
  end
87
105
 
106
+ it 'should post process the batch of records in #send_events' do
107
+ widget = Widget.create!(test_id: 'abc3', some_int: 4)
108
+ MyProducerWithPostProcess.send_events([widget])
109
+ expect(widget.reload.test_id).to eq('post_processed')
110
+ end
111
+
88
112
  end
89
113
  end
90
114
  end
@@ -0,0 +1,16 @@
1
+ RSpec.describe Schemas::MyNamespace::MySchema do
2
+ let(:key) { Schemas::MyNamespace::MySchemaKey.new(test_id: 123) }
3
+
4
+ it 'should produce a tombstone with a hash' do
5
+ result = described_class.tombstone({test_id: 123})
6
+ expect(result.payload_key).to eq(key)
7
+ expect(result.to_h).to eq({ payload_key: { 'test_id' => 123}})
8
+ end
9
+
10
+ it 'should work with a record' do
11
+ key = Schemas::MyNamespace::MySchemaKey.new(test_id: 123)
12
+ result = described_class.tombstone(key)
13
+ expect(result.payload_key).to eq(key)
14
+ expect(result.to_h).to eq({ payload_key: { 'test_id' => 123}})
15
+ end
16
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # For testing the generated class.
4
- RSpec.describe Schemas::MySchemaWithCircularReference do
4
+ RSpec.describe Schemas::MyNamespace::MySchemaWithCircularReference do
5
5
  let(:payload_hash) do
6
6
  {
7
7
  properties: {
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # For testing the generated class.
4
- RSpec.describe Schemas::MySchemaWithComplexType do
4
+ RSpec.describe Schemas::MyNamespace::MySchemaWithComplexType do
5
5
  let(:payload_hash) do
6
6
  {
7
7
  test_id: 'test id',
@@ -9,16 +9,16 @@ RSpec.describe Schemas::MySchemaWithComplexType do
9
9
  test_string_array: %w(abc def),
10
10
  test_int_array: [123, 456],
11
11
  some_integer_map: { 'int_1' => 1, 'int_2' => 2 },
12
- some_record: Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'field 1'),
13
- some_optional_record: Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'field 2'),
14
- some_record_array: [Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'field 3'),
15
- Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'field 4')],
12
+ some_record: described_class::ARecord.new(a_record_field: 'field 1'),
13
+ some_optional_record: described_class::ARecord.new(a_record_field: 'field 2'),
14
+ some_record_array: [described_class::ARecord.new(a_record_field: 'field 3'),
15
+ described_class::ARecord.new(a_record_field: 'field 4')],
16
16
  some_record_map: {
17
- 'record_1' => Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'field 5'),
18
- 'record_2' => Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'field 6')
17
+ 'record_1' => described_class::ARecord.new(a_record_field: 'field 5'),
18
+ 'record_2' => described_class::ARecord.new(a_record_field: 'field 6')
19
19
  },
20
- some_enum_array: [Schemas::MySchemaWithComplexType::AnEnum.new('sym1'),
21
- Schemas::MySchemaWithComplexType::AnEnum.new('sym2')]
20
+ some_enum_array: [described_class::AnEnum.new('sym1'),
21
+ described_class::AnEnum.new('sym2')]
22
22
  }
23
23
  end
24
24
 
@@ -51,6 +51,14 @@ RSpec.describe Schemas::MySchemaWithComplexType do
51
51
 
52
52
  end
53
53
 
54
+ describe '.tombstone' do
55
+ it 'should return a tombstone' do
56
+ record = described_class.tombstone('foo')
57
+ expect(record.tombstone_key).to eq('foo')
58
+ expect(record.to_h).to eq({payload_key: 'foo'})
59
+ end
60
+ end
61
+
54
62
  describe 'base class methods' do
55
63
  let(:klass) do
56
64
  described_class.new(**payload_hash)
@@ -116,7 +124,7 @@ RSpec.describe Schemas::MySchemaWithComplexType do
116
124
  payload_hash.delete(:some_record)
117
125
  klass = described_class.new(**payload_hash)
118
126
  expect(klass.some_record).
119
- to eq(Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'Test String'))
127
+ to eq(described_class::ARecord.new(a_record_field: 'Test String'))
120
128
  end
121
129
 
122
130
  it 'should set some_record to nil' do
@@ -139,26 +147,26 @@ RSpec.describe Schemas::MySchemaWithComplexType do
139
147
 
140
148
  it 'should get the value of some_record_array' do
141
149
  some_record_array = klass.some_record_array
142
- expect(some_record_array.first).to be_instance_of(Schemas::MySchemaWithComplexType::ARecord)
150
+ expect(some_record_array.first).to be_instance_of(described_class::ARecord)
143
151
  expect(some_record_array.first.a_record_field).to eq('field 3')
144
152
  end
145
153
 
146
154
  it 'should get the value of some_record_map' do
147
155
  some_record_map = klass.some_record_map
148
156
  expect(some_record_map['record_1']).
149
- to be_instance_of(Schemas::MySchemaWithComplexType::ARecord)
157
+ to be_instance_of(described_class::ARecord)
150
158
  expect(some_record_map['record_1'].a_record_field).to eq('field 5')
151
159
  end
152
160
 
153
161
  it 'should get the value of some_enum_array' do
154
162
  some_enum_array = klass.some_enum_array
155
- expect(some_enum_array.first).to be_instance_of(Schemas::MySchemaWithComplexType::AnEnum)
163
+ expect(some_enum_array.first).to be_instance_of(described_class::AnEnum)
156
164
  expect(some_enum_array.first.value).to eq('sym1')
157
165
  end
158
166
 
159
167
  it 'should get the value of some_record' do
160
168
  record = klass.some_record
161
- expect(record).to be_instance_of(Schemas::MySchemaWithComplexType::ARecord)
169
+ expect(record).to be_instance_of(described_class::ARecord)
162
170
  expect(record.a_record_field).to eq('field 1')
163
171
  expect(record.to_h).to eq({ 'a_record_field' => 'field 1' })
164
172
  end
@@ -180,40 +188,40 @@ RSpec.describe Schemas::MySchemaWithComplexType do
180
188
 
181
189
  it 'should modify the value of some_optional_record' do
182
190
  expect(klass.some_optional_record).
183
- to eq(Schemas::MySchemaWithComplexType::ARecord.new(a_record_field: 'field 2'))
184
- klass.some_optional_record = Schemas::MySchemaWithComplexType::ARecord.
191
+ to eq(described_class::ARecord.new(a_record_field: 'field 2'))
192
+ klass.some_optional_record = described_class::ARecord.
185
193
  new(a_record_field: 'new field')
186
194
 
187
- expect(klass.some_optional_record).to eq(Schemas::MySchemaWithComplexType::ARecord.
195
+ expect(klass.some_optional_record).to eq(described_class::ARecord.
188
196
  new(a_record_field: 'new field'))
189
197
  expect(klass.some_optional_record.as_json).to eq({ 'a_record_field' => 'new field' })
190
198
  end
191
199
 
192
200
  it 'should accept a hash object inner records' do
193
201
  klass.some_optional_record = { a_record_field: 'new field' }
194
- expect(klass.some_optional_record).to eq(Schemas::MySchemaWithComplexType::ARecord.
195
- new(a_record_field: 'new field'))
202
+ expect(klass.some_optional_record).
203
+ to eq(described_class::ARecord.new(a_record_field: 'new field'))
196
204
  expect(klass.some_optional_record.as_json).to eq({ 'a_record_field' => 'new field' })
197
205
  end
198
206
 
199
207
  it 'should modify the value of some_enum_array' do
200
208
  klass.some_enum_array.first.value = 'new_sym'
201
209
  expect(klass.some_enum_array.first).
202
- to eq(Schemas::MySchemaWithComplexType::AnEnum.new('new_sym'))
210
+ to eq(described_class::AnEnum.new('new_sym'))
203
211
 
204
- klass.some_enum_array.second.an_enum = Schemas::MySchemaWithComplexType::AnEnum.
212
+ klass.some_enum_array.second.an_enum = described_class::AnEnum.
205
213
  new('other_sym')
206
214
  expect(klass.some_enum_array.second.an_enum).to eq('other_sym')
207
215
  end
208
216
 
209
217
  it 'should modify the value of some_record_map' do
210
218
  klass.some_record_map['record_1'].a_record_field = 'new field'
211
- expect(klass.some_record_map['record_1']).to eq(Schemas::MySchemaWithComplexType::ARecord.
219
+ expect(klass.some_record_map['record_1']).to eq(described_class::ARecord.
212
220
  new(a_record_field: 'new field'))
213
221
 
214
- klass.some_record_map['record_2'] = Schemas::MySchemaWithComplexType::ARecord.
222
+ klass.some_record_map['record_2'] = described_class::ARecord.
215
223
  new(a_record_field: 'other field')
216
- expect(klass.some_record_map['record_2']).to eq(Schemas::MySchemaWithComplexType::ARecord.
224
+ expect(klass.some_record_map['record_2']).to eq(described_class::ARecord.
217
225
  new(a_record_field: 'other field'))
218
226
  end
219
227
  end
@@ -397,7 +397,7 @@ module ProducerTest
397
397
  end
398
398
  expect(MyProducer.encoder).to receive(:validate).and_raise('OH NOES')
399
399
  expect {
400
- MyProducer.publish(Schemas::MySchema.new(test_id: 'foo', some_int: 'invalid'))
400
+ MyProducer.publish(Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 'invalid'))
401
401
  }.to raise_error('OH NOES')
402
402
  Deimos.unsubscribe(subscriber)
403
403
  end
@@ -420,8 +420,8 @@ module ProducerTest
420
420
  ).and_call_original
421
421
 
422
422
  MyProducer.publish_list(
423
- [Schemas::MySchema.new(test_id: 'foo', some_int: 123),
424
- Schemas::MySchema.new(test_id: 'bar', some_int: 124)]
423
+ [Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 123),
424
+ Schemas::MyNamespace::MySchema.new(test_id: 'bar', some_int: 124)]
425
425
  )
426
426
  expect('my-topic').to have_sent('test_id' => 'foo', 'some_int' => 123)
427
427
  expect('your-topic').not_to have_sent('test_id' => 'foo', 'some_int' => 123)
@@ -432,8 +432,8 @@ module ProducerTest
432
432
  expect(described_class).not_to receive(:produce_batch)
433
433
  Deimos.configure { |c| c.producers.disabled = true }
434
434
  MyProducer.publish_list(
435
- [Schemas::MySchema.new(test_id: 'foo', some_int: 123),
436
- Schemas::MySchema.new(test_id: 'bar', some_int: 124)]
435
+ [Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 123),
436
+ Schemas::MyNamespace::MySchema.new(test_id: 'bar', some_int: 124)]
437
437
  )
438
438
  expect(MyProducer.topic).not_to have_sent(anything)
439
439
  end
@@ -452,8 +452,8 @@ module ProducerTest
452
452
  }, { topic: 'my-topic-value' })
453
453
 
454
454
  MyProducer.publish_list(
455
- [Schemas::MySchema.new(test_id: 'foo', some_int: 123),
456
- Schemas::MySchema.new(test_id: 'bar', some_int: 124)]
455
+ [Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 123),
456
+ Schemas::MyNamespace::MySchema.new(test_id: 'bar', some_int: 124)]
457
457
  )
458
458
  end
459
459
 
@@ -464,19 +464,19 @@ module ProducerTest
464
464
  { topic: 'my-topic2-key' })
465
465
 
466
466
  MySchemaProducer.publish_list(
467
- [Schemas::MySchema.new(test_id: 'foo', some_int: 123, payload_key: { 'test_id' => 'foo_key' }),
468
- Schemas::MySchema.new(test_id: 'bar', some_int: 124, payload_key: { 'test_id' => 'bar_key' })]
467
+ [Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 123, payload_key: { 'test_id' => 'foo_key' }),
468
+ Schemas::MyNamespace::MySchema.new(test_id: 'bar', some_int: 124, payload_key: { 'test_id' => 'bar_key' })]
469
469
  )
470
470
  end
471
471
 
472
472
  it 'should properly encode and coerce values with a nested record' do
473
473
  expect(MyNestedSchemaProducer.encoder).to receive(:encode_key).with('test_id', 'foo', topic: 'my-topic-key')
474
474
  MyNestedSchemaProducer.publish(
475
- Schemas::MyNestedSchema.new(
475
+ Schemas::MyNamespace::MyNestedSchema.new(
476
476
  test_id: 'foo',
477
477
  test_float: BigDecimal('123.456'),
478
478
  test_array: ['1'],
479
- some_nested_record: Schemas::MyNestedSchema::MyNestedRecord.new(
479
+ some_nested_record: Schemas::MyNamespace::MyNestedSchema::MyNestedRecord.new(
480
480
  some_int: 123,
481
481
  some_float: BigDecimal('456.789'),
482
482
  some_string: '123',