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
@@ -0,0 +1,11 @@
1
+ {
2
+ "namespace": "com.my-namespace.request",
3
+ "name": "Index",
4
+ "type": "record",
5
+ "fields": [
6
+ {
7
+ "name": "request_id",
8
+ "type": "string"
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "namespace": "com.my-namespace.request",
3
+ "name": "UpdateRequest",
4
+ "type": "record",
5
+ "fields": [
6
+ {
7
+ "name": "update_request_id",
8
+ "type": "string"
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "namespace": "com.my-namespace.response",
3
+ "name": "Index",
4
+ "type": "record",
5
+ "fields": [
6
+ {
7
+ "name": "response_id",
8
+ "type": "string"
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "namespace": "com.my-namespace.response",
3
+ "name": "UpdateResponse",
4
+ "type": "record",
5
+ "fields": [
6
+ {
7
+ "name": "update_response_id",
8
+ "type": "string"
9
+ }
10
+ ]
11
+ }
@@ -2,6 +2,8 @@
2
2
 
3
3
  $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
4
4
  require 'active_record'
5
+ require 'action_controller/railtie'
6
+ require 'database_cleaner'
5
7
  require 'deimos'
6
8
  require 'deimos/metrics/mock'
7
9
  require 'deimos/tracing/mock'
@@ -10,6 +12,11 @@ require 'active_support/testing/time_helpers'
10
12
  require 'activerecord-import'
11
13
  require 'handlers/my_batch_consumer'
12
14
  require 'handlers/my_consumer'
15
+ require 'rspec/rails'
16
+
17
+ class DeimosApp < Rails::Application
18
+ end
19
+ DeimosApp.initialize!
13
20
 
14
21
  # Helpers for Executor/DbProducer
15
22
  module TestRunners
@@ -31,6 +38,7 @@ module TestRunners
31
38
  # Test runner
32
39
  class TestRunner
33
40
  attr_accessor :id, :started, :stopped, :should_error
41
+
34
42
  # :nodoc:
35
43
  def initialize(id=nil)
36
44
  @id = id
@@ -147,6 +155,9 @@ RSpec.configure do |config|
147
155
  # true by default for RSpec 4.0
148
156
  config.shared_context_metadata_behavior = :apply_to_host_groups
149
157
 
158
+ config.filter_run(focus: true)
159
+ config.run_all_when_everything_filtered = true
160
+
150
161
  config.before(:all) do
151
162
  Time.zone = 'Eastern Time (US & Canada)'
152
163
  ActiveRecord::Base.logger = Logger.new('/dev/null')
@@ -159,6 +170,9 @@ RSpec.configure do |config|
159
170
  config.include ActiveSupport::Testing::TimeHelpers
160
171
  config.before(:suite) do
161
172
  setup_db(DbConfigs::DB_OPTIONS.last)
173
+
174
+ DatabaseCleaner.strategy = :transaction
175
+ DatabaseCleaner.clean_with(:truncation)
162
176
  end
163
177
 
164
178
  config.mock_with(:rspec) do |mocks|
@@ -179,6 +193,16 @@ RSpec.configure do |config|
179
193
  deimos_config.schema.backend = :avro_validation
180
194
  end
181
195
  end
196
+
197
+ config.around(:each) do |example|
198
+ use_cleaner = !example.metadata[:integration]
199
+
200
+ DatabaseCleaner.start if use_cleaner
201
+
202
+ example.run
203
+
204
+ DatabaseCleaner.clean if use_cleaner
205
+ end
182
206
  end
183
207
 
184
208
  RSpec.shared_context('with widgets') do
@@ -48,8 +48,8 @@ each_db_config(Deimos::Utils::DbPoller) do
48
48
  end
49
49
 
50
50
  allow(Deimos::Utils::DbPoller).to receive(:new)
51
- signal_double = instance_double(Deimos::Utils::SignalHandler, run!: nil)
52
- allow(Deimos::Utils::SignalHandler).to receive(:new).and_return(signal_double)
51
+ signal_double = instance_double(Sigurd::SignalHandler, run!: nil)
52
+ allow(Sigurd::SignalHandler).to receive(:new).and_return(signal_double)
53
53
  described_class.start!
54
54
  expect(Deimos::Utils::DbPoller).to have_received(:new).twice
55
55
  expect(Deimos::Utils::DbPoller).to have_received(:new).
@@ -16,11 +16,13 @@ each_db_config(Deimos::Utils::DbProducer) do
16
16
 
17
17
  before(:each) do
18
18
  stub_const('Deimos::Utils::DbProducer::BATCH_SIZE', 2)
19
+ stub_const('Deimos::Utils::DbProducer::DELETE_BATCH_SIZE', 1)
19
20
  end
20
21
 
21
22
  specify '#process_next_messages' do
22
23
  expect(producer).to receive(:retrieve_topics).and_return(%w(topic1 topic2))
23
24
  expect(producer).to receive(:process_topic).twice
25
+ expect(Deimos::KafkaTopicInfo).to receive(:ping_empty_topics).with(%w(topic1 topic2))
24
26
  expect(producer).to receive(:sleep).with(0.5)
25
27
  producer.process_next_messages
26
28
  end
@@ -40,6 +42,9 @@ each_db_config(Deimos::Utils::DbProducer) do
40
42
  Deimos::KafkaMessage.create!(topic: 'topic1',
41
43
  message: 'blah',
42
44
  key: "key#{i}")
45
+ Deimos::KafkaMessage.create!(topic: 'topic2',
46
+ message: 'blah',
47
+ key: "key#{i}")
43
48
  end
44
49
  stub_const('Deimos::Utils::DbProducer::BATCH_SIZE', 5)
45
50
  producer.current_topic = 'topic1'
@@ -280,6 +285,12 @@ each_db_config(Deimos::Utils::DbProducer) do
280
285
  message: "mess#{i}",
281
286
  partition_key: "key#{i}"
282
287
  )
288
+ Deimos::KafkaMessage.create!(
289
+ id: i,
290
+ topic: 'my-topic2',
291
+ message: "mess#{i}",
292
+ partition_key: "key#{i}"
293
+ )
283
294
  end
284
295
 
285
296
  expect(Deimos::KafkaTopicInfo).to receive(:lock).
@@ -288,9 +299,60 @@ each_db_config(Deimos::Utils::DbProducer) do
288
299
  expect(producer).to receive(:retrieve_messages).and_return(messages)
289
300
  expect(Deimos::KafkaTopicInfo).to receive(:register_error)
290
301
 
302
+ expect(Deimos::KafkaMessage.count).to eq(8)
303
+ producer.process_topic('my-topic')
291
304
  expect(Deimos::KafkaMessage.count).to eq(4)
305
+ end
306
+
307
+ it 'should retry deletes and not re-publish' do
308
+ messages = (1..4).map do |i|
309
+ Deimos::KafkaMessage.create!(
310
+ id: i,
311
+ topic: 'my-topic',
312
+ message: "mess#{i}",
313
+ partition_key: "key#{i}"
314
+ )
315
+ end
316
+ (5..8).each do |i|
317
+ Deimos::KafkaMessage.create!(
318
+ id: i,
319
+ topic: 'my-topic2',
320
+ message: "mess#{i}",
321
+ partition_key: "key#{i}"
322
+ )
323
+ end
324
+
325
+ raise_error = true
326
+ expect(Deimos::KafkaMessage).to receive(:where).exactly(5).times.and_wrap_original do |m, *args|
327
+ if raise_error
328
+ raise_error = false
329
+ raise 'Lock wait timeout'
330
+ end
331
+ m.call(*args)
332
+ end
333
+
334
+ expect(Deimos::KafkaTopicInfo).to receive(:lock).
335
+ with('my-topic', 'abc').and_return(true)
336
+ expect(producer).to receive(:retrieve_messages).ordered.and_return(messages)
337
+ expect(producer).to receive(:retrieve_messages).ordered.and_return([])
338
+ expect(phobos_producer).to receive(:publish_list).once.with(messages.map(&:phobos_message))
339
+
340
+ expect(Deimos::KafkaMessage.count).to eq(8)
292
341
  producer.process_topic('my-topic')
293
- expect(Deimos::KafkaMessage.count).to eq(0)
342
+ expect(Deimos::KafkaMessage.count).to eq(4)
343
+ end
344
+
345
+ it 'should re-raise misc errors on delete' do
346
+ messages = (1..3).map do |i|
347
+ Deimos::KafkaMessage.create!(
348
+ id: i,
349
+ topic: 'my-topic',
350
+ message: "mess#{i}",
351
+ partition_key: "key#{i}"
352
+ )
353
+ end
354
+ expect(Deimos::KafkaMessage).to receive(:where).once.and_raise('OH NOES')
355
+ expect { producer.delete_messages(messages) }.to raise_exception('OH NOES')
294
356
  end
295
357
 
296
358
  end
@@ -309,21 +371,34 @@ each_db_config(Deimos::Utils::DbProducer) do
309
371
  Deimos::KafkaMessage.create!(topic: "topic#{i}", message: nil,
310
372
  created_at: (1 + i).minute.ago)
311
373
  end
374
+ Deimos::KafkaTopicInfo.create!(topic: 'topic1',
375
+ last_processed_at: 6.minutes.ago)
376
+ Deimos::KafkaTopicInfo.create!(topic: 'topic2',
377
+ last_processed_at: 3.minutes.ago)
378
+ Deimos::KafkaTopicInfo.create!(topic: 'topic3',
379
+ last_processed_at: 5.minutes.ago)
312
380
  allow(Deimos.config.metrics).to receive(:gauge)
313
381
  producer.send_pending_metrics
314
- expect(Deimos.config.metrics).to have_received(:gauge).twice
382
+ expect(Deimos.config.metrics).to have_received(:gauge).exactly(6).times
383
+ # topic1 has the earliest message 4 minutes ago and last processed 6
384
+ # minutes ago, so the most amount of time we've seen nothing is 4 minutes
315
385
  expect(Deimos.config.metrics).to have_received(:gauge).
316
386
  with('pending_db_messages_max_wait', 4.minutes.to_i, tags: ['topic:topic1'])
387
+ # topic2 has earliest message 5 minutes ago and last processed 3 minutes
388
+ # ago, so we should give it 3 minutes
389
+ expect(Deimos.config.metrics).to have_received(:gauge).
390
+ with('pending_db_messages_max_wait', 3.minutes.to_i, tags: ['topic:topic2'])
391
+ # topic3 has no messages, so should get 0
317
392
  expect(Deimos.config.metrics).to have_received(:gauge).
318
- with('pending_db_messages_max_wait', 5.minutes.to_i, tags: ['topic:topic2'])
393
+ with('pending_db_messages_max_wait', 0, tags: ['topic:topic3'])
394
+ expect(Deimos.config.metrics).to have_received(:gauge).
395
+ with('pending_db_messages_count', 3, tags: ['topic:topic1'])
396
+ expect(Deimos.config.metrics).to have_received(:gauge).
397
+ with('pending_db_messages_count', 3, tags: ['topic:topic2'])
398
+ expect(Deimos.config.metrics).to have_received(:gauge).
399
+ with('pending_db_messages_count', 0, tags: ['topic:topic3'])
319
400
  end
320
401
  end
321
-
322
- it 'should send 0 if no messages' do
323
- expect(Deimos.config.metrics).to receive(:gauge).
324
- with('pending_db_messages_max_wait', 0)
325
- producer.send_pending_metrics
326
- end
327
402
  end
328
403
 
329
404
  example 'Full integration test' do
@@ -403,5 +478,4 @@ each_db_config(Deimos::Utils::DbProducer) do
403
478
  }
404
479
  ])
405
480
  end
406
-
407
481
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Deimos::Utils::DeadlockRetry do
4
+ include_context 'with widgets'
5
+
6
+ before(:each) do
7
+ allow(described_class).to receive(:sleep)
8
+ end
9
+
10
+ describe 'deadlock handling' do
11
+ let(:batch) { [{ key: 1, payload: { test_id: 'abc', some_int: 3 } }] }
12
+
13
+ it 'should retry deadlocks 3 times' do
14
+ # Should receive original attempt + 2 retries
15
+ expect(Widget).
16
+ to receive(:create).
17
+ and_raise(ActiveRecord::Deadlocked.new('Lock wait timeout exceeded')).
18
+ exactly(3).times
19
+
20
+ # After 3 tries, should let it bubble up
21
+ expect {
22
+ described_class.wrap do
23
+ Widget.create(test_id: 'abc')
24
+ end
25
+ }.to raise_error(ActiveRecord::Deadlocked)
26
+ end
27
+
28
+ it 'should stop retrying deadlocks after success' do
29
+ allow(Widget).
30
+ to receive(:create).
31
+ with(hash_including(test_id: 'first')).
32
+ and_call_original
33
+
34
+ # Fail on first attempt, succeed on second
35
+ expect(Widget).
36
+ to receive(:create).
37
+ with(hash_including(test_id: 'second')).
38
+ and_raise(ActiveRecord::Deadlocked.new('Deadlock found when trying to get lock')).
39
+ once.
40
+ ordered
41
+
42
+ expect(Widget).
43
+ to receive(:create).
44
+ with(hash_including(test_id: 'second')).
45
+ once.
46
+ ordered.
47
+ and_call_original
48
+
49
+ # Should not raise anything
50
+ described_class.wrap do
51
+ Widget.create(test_id: 'first')
52
+ Widget.create(test_id: 'second')
53
+ end
54
+
55
+ expect(Widget.all).to match_array([
56
+ have_attributes(test_id: 'first'),
57
+ have_attributes(test_id: 'second')
58
+ ])
59
+ end
60
+
61
+ it 'should not retry non-deadlock exceptions' do
62
+ expect(Widget).
63
+ to receive(:create).
64
+ and_raise(ActiveRecord::StatementInvalid.new('Oops!!')).
65
+ once
66
+
67
+ expect {
68
+ described_class.wrap do
69
+ Widget.create(test_id: 'abc')
70
+ end
71
+ }.to raise_error(ActiveRecord::StatementInvalid, 'Oops!!')
72
+ end
73
+ end
74
+ end
@@ -2,8 +2,11 @@
2
2
 
3
3
  describe Deimos::Utils::LagReporter do
4
4
 
5
+ let(:kafka_client) { instance_double(Kafka::Client) }
6
+ let(:partition1_tags) { %w(consumer_group:group1 partition:1 topic:my-topic) }
7
+ let(:partition2_tags) { %w(consumer_group:group1 partition:2 topic:my-topic) }
8
+
5
9
  before(:each) do
6
- kafka_client = instance_double(Kafka::Client)
7
10
  allow(kafka_client).to receive(:last_offset_for).and_return(100)
8
11
  allow(Phobos).to receive(:create_kafka_client).and_return(kafka_client)
9
12
  Deimos.configure { |c| c.consumers.report_lag = true }
@@ -20,38 +23,22 @@ describe Deimos::Utils::LagReporter do
20
23
  'heartbeat.consumer.kafka',
21
24
  group_id: 'group1', topic_partitions: { 'my-topic': [1] }
22
25
  )
23
-
24
26
  end
25
27
 
26
28
  it 'should report lag' do
27
29
  expect(Deimos.config.metrics).to receive(:gauge).ordered.twice.
28
- with('consumer_lag', 95,
29
- tags: %w(
30
- consumer_group:group1
31
- partition:1
32
- topic:my-topic
33
- ))
30
+ with('consumer_lag', 95, tags: partition1_tags)
34
31
  expect(Deimos.config.metrics).to receive(:gauge).ordered.once.
35
- with('consumer_lag', 80,
36
- tags: %w(
37
- consumer_group:group1
38
- partition:2
39
- topic:my-topic
40
- ))
32
+ with('consumer_lag', 80, tags: partition2_tags)
41
33
  expect(Deimos.config.metrics).to receive(:gauge).ordered.once.
42
- with('consumer_lag', 0,
43
- tags: %w(
44
- consumer_group:group1
45
- partition:2
46
- topic:my-topic
47
- ))
34
+ with('consumer_lag', 0, tags: partition2_tags)
48
35
  ActiveSupport::Notifications.instrument(
49
36
  'seek.consumer.kafka',
50
37
  offset: 5, topic: 'my-topic', group_id: 'group1', partition: 1
51
38
  )
52
39
  ActiveSupport::Notifications.instrument(
53
40
  'start_process_message.consumer.kafka',
54
- offset_lag: 80, topic: 'my-topic', group_id: 'group1', partition: 2
41
+ offset: 20, topic: 'my-topic', group_id: 'group1', partition: 2
55
42
  )
56
43
  ActiveSupport::Notifications.instrument(
57
44
  'heartbeat.consumer.kafka',
@@ -59,8 +46,28 @@ describe Deimos::Utils::LagReporter do
59
46
  )
60
47
  ActiveSupport::Notifications.instrument(
61
48
  'start_process_batch.consumer.kafka',
62
- offset_lag: 0, topic: 'my-topic', group_id: 'group1', partition: 2
49
+ last_offset: 100, topic: 'my-topic', group_id: 'group1', partition: 2
50
+ )
51
+ ActiveSupport::Notifications.instrument(
52
+ 'heartbeat.consumer.kafka',
53
+ group_id: 'group1', topic_partitions: { 'my-topic': [1, 2] }
54
+ )
55
+ end
56
+
57
+ it 'should update lag after heartbeat' do
58
+ expect(Deimos.config.metrics).to receive(:gauge).ordered.once.
59
+ with('consumer_lag', 94, tags: partition2_tags)
60
+ expect(Deimos.config.metrics).to receive(:gauge).ordered.once.
61
+ with('consumer_lag', 95, tags: partition2_tags)
62
+ ActiveSupport::Notifications.instrument(
63
+ 'seek.consumer.kafka',
64
+ offset: 6, topic: 'my-topic', group_id: 'group1', partition: 2
65
+ )
66
+ ActiveSupport::Notifications.instrument(
67
+ 'heartbeat.consumer.kafka',
68
+ group_id: 'group1', topic_partitions: { 'my-topic': [1, 2] }
63
69
  )
70
+ allow(kafka_client).to receive(:last_offset_for).and_return(101)
64
71
  ActiveSupport::Notifications.instrument(
65
72
  'heartbeat.consumer.kafka',
66
73
  group_id: 'group1', topic_partitions: { 'my-topic': [1, 2] }
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'deimos/utils/schema_controller_mixin'
4
+ require 'deimos/schema_backends/avro_local'
5
+
6
+ RSpec.describe Deimos::Utils::SchemaControllerMixin, type: :controller do
7
+
8
+ before(:each) do
9
+ Deimos.configure do
10
+ schema.backend(:avro_local)
11
+ end
12
+ end
13
+
14
+ controller(ActionController::Base) do
15
+ include Deimos::Utils::SchemaControllerMixin # rubocop:disable RSpec/DescribedClass
16
+
17
+ request_namespace 'com.my-namespace.request'
18
+ response_namespace 'com.my-namespace.response'
19
+ schemas :index, :show
20
+ schemas :update, request: 'UpdateRequest', response: 'UpdateResponse'
21
+
22
+ # :nodoc:
23
+ def index
24
+ render_schema({ 'response_id' => payload[:request_id] + ' mom' })
25
+ end
26
+
27
+ # :nodoc:
28
+ def show
29
+ render_schema({ 'response_id' => payload[:request_id] + ' dad' })
30
+ end
31
+
32
+ # :nodoc:
33
+ def update
34
+ render_schema({ 'update_response_id' => payload[:update_request_id] + ' sis' })
35
+ end
36
+ end
37
+
38
+ it 'should render the correct response for index' do
39
+ request_backend = Deimos.schema_backend(schema: 'Index',
40
+ namespace: 'com.my-namespace.request')
41
+ response_backend = Deimos.schema_backend(schema: 'Index',
42
+ namespace: 'com.my-namespace.response')
43
+ request.content_type = 'avro/binary'
44
+ get :index, body: request_backend.encode({ 'request_id' => 'hi' })
45
+ expect(response_backend.decode(response.body)).to eq({ 'response_id' => 'hi mom' })
46
+ end
47
+
48
+ it 'should render the correct response for show' do
49
+ request_backend = Deimos.schema_backend(schema: 'Index',
50
+ namespace: 'com.my-namespace.request')
51
+ response_backend = Deimos.schema_backend(schema: 'Index',
52
+ namespace: 'com.my-namespace.response')
53
+ request.content_type = 'avro/binary'
54
+ get :show, params: { id: 1 }, body: request_backend.encode({ 'request_id' => 'hi' })
55
+ expect(response_backend.decode(response.body)).to eq({ 'response_id' => 'hi dad' })
56
+ end
57
+
58
+ it 'should render the correct response for update' do
59
+ request_backend = Deimos.schema_backend(schema: 'UpdateRequest',
60
+ namespace: 'com.my-namespace.request')
61
+ response_backend = Deimos.schema_backend(schema: 'UpdateResponse',
62
+ namespace: 'com.my-namespace.response')
63
+ request.content_type = 'avro/binary'
64
+ post :update, params: { id: 1 }, body: request_backend.encode({ 'update_request_id' => 'hi' })
65
+ expect(response_backend.decode(response.body)).to eq({ 'update_response_id' => 'hi sis' })
66
+ end
67
+
68
+ end