nulogy_message_bus_producer 1.0.2
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.
- checksums.yaml +7 -0
- data/README.md +35 -0
- data/Rakefile +22 -0
- data/db/migrate/20200611150212_create_public_subscriptions_and_events_tables.rb +25 -0
- data/lib/nulogy_message_bus_producer.rb +112 -0
- data/lib/nulogy_message_bus_producer/application_record.rb +6 -0
- data/lib/nulogy_message_bus_producer/base_public_subscription.rb +13 -0
- data/lib/nulogy_message_bus_producer/engine.rb +6 -0
- data/lib/nulogy_message_bus_producer/postgres_public_subscriptions.rb +102 -0
- data/lib/nulogy_message_bus_producer/public_subscription.rb +27 -0
- data/lib/nulogy_message_bus_producer/public_subscription_event.rb +13 -0
- data/lib/nulogy_message_bus_producer/subscriber_graphql_schema_validator.rb +45 -0
- data/lib/nulogy_message_bus_producer/version.rb +3 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +4 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/javascripts/cable.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +7 -0
- data/spec/dummy/app/controllers/dummy_controller.rb +17 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/jobs/application_job.rb +2 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +38 -0
- data/spec/dummy/bin/update +29 -0
- data/spec/dummy/bin/yarn +11 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/config/application.rb +22 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/cable.yml +10 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +54 -0
- data/spec/dummy/config/environments/production.rb +91 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy/config/initializers/assets.rb +14 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +33 -0
- data/spec/dummy/config/puma.rb +56 -0
- data/spec/dummy/config/routes.rb +6 -0
- data/spec/dummy/config/secrets.yml +32 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/db/schema.rb +42 -0
- data/spec/dummy/log/development.log +1771 -0
- data/spec/dummy/log/test.log +14189 -0
- data/spec/dummy/package.json +5 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/integration/lib/graphql_api/postgres_public_subscriptions_spec.rb +16 -0
- data/spec/integration/lib/graphql_api/validators/subscriber_graphql_schema_validator_spec.rb +76 -0
- data/spec/integration_spec_helper.rb +35 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/unit/lib/graphql_api/models/public_subscription_spec.rb +56 -0
- data/spec/unit_spec_helper.rb +6 -0
- metadata +342 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d983bc5429dfc09c434c773bcd93d71a6bb26fe72a14fe16c95a2d0819f1e540
|
4
|
+
data.tar.gz: 15b57a37e9a6975ef474826fb2156071d19f6b95c7d800e98ea39de36908ad80
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5b7971fa352fbfbbf7ec0d2f8f190eb9901a7dccdb76b121b8a20459f231e76d89b59994f29a66c90b713458b6c5e9367559a5663af78b38ef5bc09728663d68
|
7
|
+
data.tar.gz: 37e525876eedc66d78d3b22d5b9f47f610bfe7e08f352054cd194d50096740ab16058c1dcb4e2a260a4de2b55fe9a77bfd995162a9772c0991eb0ab4246f7151
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Nulogy Message Bus Producer
|
2
|
+
|
3
|
+
Nulogy's code for producing to to the Message Bus
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
1. Add the gem to your Gemfile `gem "nulogy_message_bus_producer"`
|
8
|
+
2. Install the migration `rake railties:install:migrations`
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
This engine contains the classes and validations for producing messages to the Message Bus.
|
13
|
+
|
14
|
+
In general, as long as a subscription inherits from `NulogyMessageBusProducer::BasePublicSubscription`, everything
|
15
|
+
should be set up.
|
16
|
+
|
17
|
+
Subscriptions will be written to `public_subscriptions` while events generated from the subscriptions will be written to
|
18
|
+
`public_subscription_events`. Debezium then reads this table from the PG replication log and pushes them into Kafka.
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
| Configuration | Default | Description |
|
23
|
+
|--------------------------------|---------------------------------|--------------------------------------------------------------|
|
24
|
+
| subscriptions_table_name | message_bus_subscriptions | The name of the table for the PublicSubscription model |
|
25
|
+
| subscription_events_table_name | message_bus_subscription_events | The name of the table for the PublicSubscriptionEvents model |
|
26
|
+
|
27
|
+
## Initializer
|
28
|
+
|
29
|
+
There is an initializer (see `engine.rb`) that validates if the current `public_subscriptions.query` queries are valid
|
30
|
+
against their appropriate GraphQL schema.
|
31
|
+
|
32
|
+
## Rake Tasks
|
33
|
+
|
34
|
+
`rake spec` - Run the specs
|
35
|
+
`rake rubocop` - Run RuboCop
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require "bundler/setup"
|
4
|
+
rescue LoadError
|
5
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
6
|
+
end
|
7
|
+
|
8
|
+
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
|
9
|
+
load "rails/tasks/engine.rake"
|
10
|
+
|
11
|
+
Bundler::GemHelper.install_tasks
|
12
|
+
|
13
|
+
require "rspec/core"
|
14
|
+
require "rspec/core/rake_task"
|
15
|
+
|
16
|
+
RSpec::Core::RakeTask.new(:spec)
|
17
|
+
|
18
|
+
require "rubocop/rake_task"
|
19
|
+
|
20
|
+
RuboCop::RakeTask.new
|
21
|
+
|
22
|
+
task default: [:spec, :rubocop]
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class CreatePublicSubscriptionsAndEventsTables < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
# TODO: You may need to tweak this setup to suit your app's database
|
4
|
+
enable_extension "uuid-ossp"
|
5
|
+
|
6
|
+
create_table NulogyMessageBusProducer.subscriptions_table_name, id: :uuid, default: nil do |t|
|
7
|
+
t.uuid :subscription_group_id, null: false
|
8
|
+
t.string :event_type, null: false, index: { name: "index_nulogy_mb_producer_subscriptions_on_event_type" }
|
9
|
+
t.string :topic_name, null: false
|
10
|
+
t.string :query, null: false
|
11
|
+
t.text :schema_key, null: false
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table NulogyMessageBusProducer.subscription_events_table_name, id: :uuid, default: nil do |t|
|
17
|
+
t.uuid :public_subscription_id, null: false
|
18
|
+
t.string :partition_key, null: false
|
19
|
+
t.string :topic_name, null: false
|
20
|
+
t.uuid :tenant_id, null: false
|
21
|
+
t.json :event_json, null: false
|
22
|
+
t.column :created_at, :datetime, index: { name: "index_nulogy_mb_producer_subscription_events_on_created_at" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "graphql"
|
2
|
+
require "strong_migrations"
|
3
|
+
|
4
|
+
require "nulogy_message_bus_producer/version"
|
5
|
+
require "nulogy_message_bus_producer/engine"
|
6
|
+
|
7
|
+
# The gem and its configuration
|
8
|
+
module NulogyMessageBusProducer
|
9
|
+
mattr_reader :registered_schemas, default: {}
|
10
|
+
|
11
|
+
def self.subscriptions_table_name=(table_name)
|
12
|
+
NulogyMessageBusProducer::PublicSubscription.table_name = table_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.subscriptions_table_name
|
16
|
+
NulogyMessageBusProducer::PublicSubscription.table_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.subscription_events_table_name=(table_name)
|
20
|
+
NulogyMessageBusProducer::PublicSubscriptionEvent.table_name = table_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.subscription_events_table_name
|
24
|
+
NulogyMessageBusProducer::PublicSubscriptionEvent.table_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.register_schema(schema_key, schema_name)
|
28
|
+
registered_schemas[schema_key] = schema_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.resolve_schema(schema_key)
|
32
|
+
registered_schemas.fetch(schema_key) do
|
33
|
+
raise KeyError, <<~MESSAGE unless block_given?
|
34
|
+
The schema registry did not contain an entry for the schema key '#{schema_key}'.
|
35
|
+
|
36
|
+
Please register the schema first with `NulogyMessageBusProducer.schemas.register(schema_key, schema)`
|
37
|
+
MESSAGE
|
38
|
+
|
39
|
+
yield
|
40
|
+
end.constantize
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.resolve_schema_key(schema)
|
44
|
+
registered_schemas.invert.fetch(schema.class.name) do
|
45
|
+
raise KeyError, <<~MESSAGE
|
46
|
+
The schema registry did not contain an entry for the schema '#{schema.class.name}'.
|
47
|
+
|
48
|
+
Please register the schema first with `NulogyMessageBusProducer.schemas.register(schema_key, schema)`
|
49
|
+
MESSAGE
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.validate_existing!
|
54
|
+
return unless Db.exists? && Db.subscriptions_exist?
|
55
|
+
|
56
|
+
validator = NulogyMessageBusProducer::SubscriberGraphqlSchemaValidator.new
|
57
|
+
|
58
|
+
return if validator.validate
|
59
|
+
|
60
|
+
raise <<~MESSAGE
|
61
|
+
#{'#' * 80}
|
62
|
+
|
63
|
+
The GraphQL queries stored in public_subscriptions.query must always remain valid against the current schema.
|
64
|
+
If one is not valid, a domain event firing could fail and users would not be able to perform critical duties
|
65
|
+
(e.g. adding production).
|
66
|
+
|
67
|
+
Note that you may experience errors in different environments, e.g. NA fails but EU passes.
|
68
|
+
If you can quickly fix the data, it is recommended you fix the data and roll forward for the failing
|
69
|
+
environment.
|
70
|
+
|
71
|
+
If you need more time to plan or execute an action, it is advised that you rollback the deployment
|
72
|
+
for all environments so that they are consistent.
|
73
|
+
|
74
|
+
The following errors were found while validating those queries against its respective schema:
|
75
|
+
|
76
|
+
#{validator.errors.join("\n")}
|
77
|
+
|
78
|
+
#{'#' * 80}
|
79
|
+
MESSAGE
|
80
|
+
end
|
81
|
+
|
82
|
+
# A private helper module to check database connectivity and setup for the above initializer
|
83
|
+
module Db
|
84
|
+
module_function
|
85
|
+
|
86
|
+
def exists?
|
87
|
+
ActiveRecord::Base.connection
|
88
|
+
rescue ActiveRecord::NoDatabaseError, PG::ConnectionBad
|
89
|
+
false
|
90
|
+
else
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def subscriptions_exist?
|
95
|
+
ActiveRecord::Base
|
96
|
+
.connection
|
97
|
+
.exec_query(
|
98
|
+
"SELECT tablename FROM pg_tables WHERE tablename = '#{NulogyMessageBusProducer.subscriptions_table_name}' AND schemaname = 'public';"
|
99
|
+
).present?
|
100
|
+
rescue # rubocop:disable Style/RescueStandardError
|
101
|
+
false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
private_constant :Db
|
105
|
+
end
|
106
|
+
|
107
|
+
require "nulogy_message_bus_producer/application_record"
|
108
|
+
require "nulogy_message_bus_producer/base_public_subscription"
|
109
|
+
require "nulogy_message_bus_producer/postgres_public_subscriptions"
|
110
|
+
require "nulogy_message_bus_producer/public_subscription"
|
111
|
+
require "nulogy_message_bus_producer/public_subscription_event"
|
112
|
+
require "nulogy_message_bus_producer/subscriber_graphql_schema_validator"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module NulogyMessageBusProducer
|
2
|
+
# This base class contains the fields required to create a subscription.
|
3
|
+
# For example, for a subscription to a model called AggregateRoot:
|
4
|
+
#
|
5
|
+
# class AggregateRootCreated < NulogyMessageBusProducer::BasePublicSubscription
|
6
|
+
# field :aggregate_root, Domain::Public::Types::AggregateRootType, null: true
|
7
|
+
# end
|
8
|
+
class BasePublicSubscription < GraphQL::Schema::Subscription
|
9
|
+
argument :subscription_id, ID, required: true
|
10
|
+
argument :subscription_group_id, ID, required: true
|
11
|
+
argument :topic_name, String, required: true
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module NulogyMessageBusProducer
|
2
|
+
# Subscription class to `use` when developing Message Bus-backed subscriptions
|
3
|
+
# For example,
|
4
|
+
#
|
5
|
+
# class SomeSchema < GraphQL::Schema
|
6
|
+
# ...
|
7
|
+
# use NulogyMessageBusProducer::PostgresPublicSubscriptions
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# It expects that schema to already be registered, or will raise an error.
|
11
|
+
#
|
12
|
+
# NulogyMessageBusProducer.register_schema("some_schema", "SomeSchema")
|
13
|
+
class PostgresPublicSubscriptions < GraphQL::Subscriptions
|
14
|
+
def initialize(options = {})
|
15
|
+
super
|
16
|
+
|
17
|
+
@schema_key = NulogyMessageBusProducer.resolve_schema_key(options.fetch(:schema))
|
18
|
+
end
|
19
|
+
|
20
|
+
# This method is copied from GraphQL::Subscriptions and customized.
|
21
|
+
# Check for changes in the superclass when upgrading the graphql gem.
|
22
|
+
def execute(subscription_id, event, object) # rubocop:disable Metrics/MethodLength
|
23
|
+
query_data = read_subscription(subscription_id)
|
24
|
+
query_string = query_data.fetch(:query_string)
|
25
|
+
variables = { id: object[:uuid] }
|
26
|
+
context = object[:context]
|
27
|
+
operation_name = query_data.fetch(:operation_name)
|
28
|
+
result = @schema.execute(
|
29
|
+
query: query_string,
|
30
|
+
context: context,
|
31
|
+
subscription_topic: event.topic,
|
32
|
+
operation_name: operation_name,
|
33
|
+
variables: variables,
|
34
|
+
root_value: object
|
35
|
+
)
|
36
|
+
deliver(subscription_id, result)
|
37
|
+
rescue GraphQL::Schema::Subscription::NoUpdateError
|
38
|
+
# This update was skipped in user code; do nothing.
|
39
|
+
rescue GraphQL::Schema::Subscription::UnsubscribedError
|
40
|
+
delete_subscription(subscription_id)
|
41
|
+
end
|
42
|
+
|
43
|
+
def each_subscription_id(event)
|
44
|
+
Models::PublicSubscription.where(event_type: event.name, schema_key: @schema_key).each do |subscription|
|
45
|
+
yield subscription.id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_subscription(subscription_id)
|
50
|
+
query_string = Models::PublicSubscription.find_by(id: subscription_id).query
|
51
|
+
|
52
|
+
{
|
53
|
+
query_string: query_string,
|
54
|
+
operation_name: nil
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def deliver(subscription_id, result)
|
59
|
+
tenant_id = result.query.context.object[:tenant_id]
|
60
|
+
subscription = Models::PublicSubscription.find_by(id: subscription_id)
|
61
|
+
|
62
|
+
Models::PublicSubscriptionEvent.create_or_update(
|
63
|
+
id: SecureRandom.uuid,
|
64
|
+
public_subscription_id: subscription_id,
|
65
|
+
partition_key: "#{subscription.subscription_group_id},#{tenant_id}",
|
66
|
+
tenant_id: tenant_id,
|
67
|
+
event_json: result.to_h["data"],
|
68
|
+
topic_name: subscription.topic_name
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
def write_subscription(query, events)
|
73
|
+
events.each do |event|
|
74
|
+
Models::PublicSubscription.create_or_update(
|
75
|
+
id: event.arguments[:subscription_id],
|
76
|
+
subscription_group_id: event.arguments[:subscription_group_id],
|
77
|
+
event_type: event.name,
|
78
|
+
schema_key: @schema_key,
|
79
|
+
query: convert_subscription_result_query_to_regular_query(query, event),
|
80
|
+
topic_name: event.arguments[:topic_name]
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def delete_subscription(subscription_id)
|
86
|
+
Models::PublicSubscription.find_by(id: subscription_id).destroy
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def convert_subscription_result_query_to_regular_query(query, event)
|
92
|
+
selections = query.document.definitions.first.selections
|
93
|
+
|
94
|
+
event_selection = selections.find { |e| e.name == event.name }
|
95
|
+
|
96
|
+
# TODO: This assumes the query_type.rb takes an argument called 'id'. This should check the query to lookup the argument name
|
97
|
+
# TODO: Can we do this by manipulating GQL objects?
|
98
|
+
inner_query = event_selection.selections.first.to_query_string.sub("{", "(id: $id) {")
|
99
|
+
"query ($id: UUID!) { #{inner_query} }"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module NulogyMessageBusProducer
|
2
|
+
# This model saves all subscriptions to external systems.
|
3
|
+
# An external system can subscribe to events and specify the shape of data it would like to receive for the event.
|
4
|
+
class PublicSubscription < ApplicationRecord
|
5
|
+
self.table_name = :message_bus_subscriptions
|
6
|
+
|
7
|
+
# Run our validator with familar syntax in this model
|
8
|
+
class ValidForSchemaValidator < ActiveModel::EachValidator
|
9
|
+
def validate_each(record, attribute, _value)
|
10
|
+
validator = NulogyMessageBusProducer::SubscriberGraphqlSchemaValidator.new
|
11
|
+
|
12
|
+
validator.validate(record)
|
13
|
+
|
14
|
+
validator.errors.each { |e| record.errors.add(attribute, e) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
validates :query, presence: true, valid_for_schema: true
|
19
|
+
validates :schema_key, presence: true
|
20
|
+
|
21
|
+
def self.create_or_update(attrs)
|
22
|
+
find_or_initialize_by(id: attrs[:id]).tap do |model|
|
23
|
+
model.update!(attrs)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module NulogyMessageBusProducer
|
2
|
+
# A model that contains the event data for a particular subscription
|
3
|
+
# It is simply saved in the database and shipped to Kafka by Debezium
|
4
|
+
class PublicSubscriptionEvent < ApplicationRecord
|
5
|
+
self.table_name = :message_bus_subscription_events
|
6
|
+
|
7
|
+
def self.create_or_update(attrs)
|
8
|
+
find_or_initialize_by(id: attrs[:id]).tap do |model|
|
9
|
+
model.update!(attrs)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module NulogyMessageBusProducer
|
2
|
+
# A custom validator that checks that the provided (or all) subscriptions have a query that is valid for its
|
3
|
+
# configured schema. Schemas must be registered with a `schema_key`, that is persisted in the database.
|
4
|
+
# It ties the subscription to a particular schema.
|
5
|
+
#
|
6
|
+
# This validator is run as part of an initializer as a last ditch effort to verify that the stored queries in the
|
7
|
+
# database are valid against the deployed schema, so that when events are generated in the system, they are always
|
8
|
+
# sucessfully created.
|
9
|
+
class SubscriberGraphqlSchemaValidator
|
10
|
+
attr_reader :errors
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@errors = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate(subscription_or_subscriptions = NulogyMessageBusProducer::PublicSubscription.all)
|
17
|
+
Array(subscription_or_subscriptions).each do |subscription|
|
18
|
+
schema = find_schema(subscription)
|
19
|
+
next unless schema
|
20
|
+
|
21
|
+
gql_errors = schema.validate(subscription.query)
|
22
|
+
errors = gql_errors.map { |e| "#{e.message} #{display_id(subscription.id)}" }
|
23
|
+
|
24
|
+
@errors.concat(errors)
|
25
|
+
end
|
26
|
+
|
27
|
+
@errors.empty?
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def find_schema(subscription)
|
33
|
+
NulogyMessageBusProducer.resolve_schema(subscription.schema_key) do
|
34
|
+
@errors << "Could not find a schema for schema_key '#{subscription.schema_key}' #{display_id(subscription.id)}"
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def display_id(id)
|
40
|
+
normalized = id.presence || "<new_record>"
|
41
|
+
|
42
|
+
"(id: #{normalized})"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/dummy/Rakefile
ADDED