nulogy_message_bus_producer 3.2.1 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +82 -22
  3. data/Rakefile +2 -4
  4. data/db/migrate/20200611150212_create_public_subscriptions_and_events_tables.rb +2 -2
  5. data/lib/nulogy_message_bus_producer.rb +15 -8
  6. data/lib/nulogy_message_bus_producer/base_subscription.rb +1 -1
  7. data/lib/nulogy_message_bus_producer/config.rb +25 -1
  8. data/lib/nulogy_message_bus_producer/configuration/query_parser.rb +71 -0
  9. data/lib/nulogy_message_bus_producer/self_serve_subscription.rb +18 -0
  10. data/lib/nulogy_message_bus_producer/subscriptions/configured_subscription.rb +14 -0
  11. data/lib/nulogy_message_bus_producer/subscriptions/finder.rb +40 -0
  12. data/lib/nulogy_message_bus_producer/subscriptions/postgres_transport.rb +13 -6
  13. data/lib/nulogy_message_bus_producer/subscriptions/query_validator.rb +47 -0
  14. data/lib/nulogy_message_bus_producer/subscriptions/risky_subscription_blocker.rb +0 -5
  15. data/lib/nulogy_message_bus_producer/subscriptions/valid_for_schema_validator.rb +14 -0
  16. data/lib/nulogy_message_bus_producer/version.rb +1 -1
  17. data/spec/dummy/Rakefile +1 -1
  18. data/spec/dummy/app/mailers/application_mailer.rb +2 -2
  19. data/spec/dummy/bin/bundle +2 -2
  20. data/spec/dummy/bin/rails +3 -3
  21. data/spec/dummy/bin/rake +2 -2
  22. data/spec/dummy/bin/setup +14 -16
  23. data/spec/dummy/bin/update +10 -10
  24. data/spec/dummy/bin/yarn +13 -7
  25. data/spec/dummy/config.ru +2 -1
  26. data/spec/dummy/config/application.rb +11 -6
  27. data/spec/dummy/config/boot.rb +2 -4
  28. data/spec/dummy/config/cable.yml +2 -2
  29. data/spec/dummy/config/database.yml +2 -2
  30. data/spec/dummy/config/environment.rb +1 -1
  31. data/spec/dummy/config/environments/development.rb +29 -7
  32. data/spec/dummy/config/environments/production.rb +50 -20
  33. data/spec/dummy/config/environments/test.rb +25 -8
  34. data/spec/dummy/config/initializers/assets.rb +2 -2
  35. data/spec/dummy/config/initializers/backtrace_silencers.rb +4 -3
  36. data/spec/dummy/config/initializers/content_security_policy.rb +30 -0
  37. data/spec/dummy/config/initializers/filter_parameter_logging.rb +3 -1
  38. data/spec/dummy/config/initializers/new_framework_defaults_6_1.rb +67 -0
  39. data/spec/dummy/config/initializers/permissions_policy.rb +11 -0
  40. data/spec/dummy/config/locales/en.yml +1 -1
  41. data/spec/dummy/config/puma.rb +3 -3
  42. data/spec/dummy/config/spring.rb +2 -2
  43. data/spec/dummy/config/storage.yml +34 -0
  44. data/spec/dummy/db/schema.rb +0 -2
  45. data/spec/dummy/log/development.log +317 -0
  46. data/spec/dummy/log/test.log +13164 -0
  47. data/spec/integration/lib/nulogy_message_bus_producer/config_spec.rb +37 -0
  48. data/spec/integration/lib/nulogy_message_bus_producer/repopulate_replication_slots_spec.rb +6 -7
  49. data/spec/integration/lib/nulogy_message_bus_producer/subscription_spec.rb +3 -57
  50. data/spec/integration/lib/nulogy_message_bus_producer/subscriptions/finder_spec.rb +54 -0
  51. data/spec/integration/lib/nulogy_message_bus_producer/subscriptions/no_variables_spec.rb +1 -1
  52. data/spec/integration/lib/nulogy_message_bus_producer/subscriptions/postgres_transport_spec.rb +100 -54
  53. data/spec/integration/lib/nulogy_message_bus_producer/{subscriber_graphql_schema_validator_spec.rb → subscriptions/query_validator_spec.rb} +3 -3
  54. data/spec/integration/lib/nulogy_message_bus_producer/subscriptions/risky_subscription_blocker_spec.rb +0 -16
  55. data/spec/integration_spec_helper.rb +0 -6
  56. data/spec/nulogy_message_bus_producer/configuration/query_parser_spec.rb +58 -0
  57. data/spec/nulogy_message_bus_producer/subscriptions/subscription_spec.rb +9 -0
  58. data/spec/spec_helper.rb +26 -1
  59. data/spec/support/kafka.rb +9 -10
  60. data/spec/support/kafka_connect.rb +1 -1
  61. data/spec/support/shared_examples/subscription_validations.rb +77 -0
  62. data/spec/support/skip.rb +9 -0
  63. data/spec/support/sql_helpers.rb +1 -1
  64. data/spec/support/subscription_helpers.rb +22 -4
  65. data/spec/support/test_graphql_schema.rb +6 -2
  66. metadata +131 -79
  67. data/lib/nulogy_message_bus_producer/subscriber_graphql_schema_validator.rb +0 -45
  68. data/lib/nulogy_message_bus_producer/subscription.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b81166f96e6dc18fa79dcd9a3d5fd56785e929866c9f6c2bf1571c3b7ca3965d
4
- data.tar.gz: e0d7c148e751180d9f336146a17cb56b343d9459af5f436a452a4af4649904d3
3
+ metadata.gz: 42a5548fe112238674907a4b18853f42dcabbda48fb49dd711b824850b468c09
4
+ data.tar.gz: 7a33a695535255230f8ac46c6ddc75a0a343d8936d59f4b72e5d020b3b11b25a
5
5
  SHA512:
6
- metadata.gz: 9aaf43cc6e873323874a31baa272fcb00ac8b4792b9bead305510ea3f52ec236e5654c3bdcbf5630a3af1466530e434e20958d4134cf75df5cbaf8c16d8a4416
7
- data.tar.gz: 33e75bf74472c78810a433036a9658736e9f4b6cb8d506092ffb631bd3a9092ed914be9bb5196783e83d95dcfbabb34b8d45cbdb964154121f95f5caa8f75f14
6
+ metadata.gz: acf3750d5d987a1ecbec10258ea543095bd65b5a9e878eb7c73cc1e893a12e4ca14d13d3f3de0af97cc6796877f3995c11c9f99675f2b7437e4b91c0903f7de2
7
+ data.tar.gz: bc421953022e2682d89388d5b3ee02b4ee4194d9eba044b8b6ead775ebd166faee40927b2abe393904d26bcaa861eceae464c407a85541f1de5750227f6932e3
data/README.md CHANGED
@@ -1,39 +1,93 @@
1
1
  # Nulogy Message Bus Producer
2
2
 
3
- Nulogy's code for producing to to the Message Bus
3
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
4
+
5
+ This engine contains the classes and validations for producing messages to the Message Bus.
4
6
 
5
7
  ## Installation
6
8
 
7
- 1. Add the gem to your Gemfile `gem "nulogy_message_bus_producer"`
8
- 2. Install the migration `rake railties:install:migrations`
9
+ 1. Add the gem to your Gemfile: `gem "nulogy_message_bus_producer"`
10
+ 2. Install the migrations: `rake railties:install:migrations`
11
+ 3. Use the [Nulogy GraphQL API](https://github.com/nulogy/nulogy_graphql_api)'s schema specs to [ensure schema changes are safe](https://github.com/nulogy/nulogy_graphql_api#schema-generation)
9
12
 
10
13
  ## Usage
11
14
 
12
- This engine contains the classes and validations for producing messages to the Message Bus.
15
+ Subscriptions should inherit from `NulogyMessageBusProducer::BaseSubscription`.
16
+
17
+ ### Subscriptions
18
+
19
+ Subscriptions are created by consumers to subscribe to certain events that the producer exposes.
20
+
21
+ When an event is fired/triggered, subscriptions are used to generate events into the
22
+ `NulogyMessageBusProducer.subscription_events_table_name` table.
23
+
24
+ Debezium then reads this table from the PG replication log and pushes them into Kafka.
13
25
 
14
- In general, as long as a subscription inherits from `NulogyMessageBusProducer::BaseSubscription`, everything
15
- should be set up.
26
+ There are two ways to create subscriptions:
16
27
 
17
- Subscriptions will be written to the `NulogyMessageBusProducer.subscriptions_table_name` while events generated from the subscriptions will be written to
18
- `NulogyMessageBusProducer.subscription_events_table_name`. Debezium then reads this table from the PG replication log and pushes them into Kafka.
28
+ #### Configured
29
+
30
+ Subscriptions provided by configuration in the producer app:
31
+
32
+ ```ruby
33
+ NulogyMessageBusProducer.configure do |c|
34
+ c.register_schema(schema: "ExampleDomain::Schema", key: "exampleDomain")
35
+
36
+ c.add_subscription!(
37
+ schema: "ExampleDomain::Schema",
38
+ query: <<~QUERY
39
+ subscription {
40
+ domainEvent(subscriptionId: "uuid", subscriptionGroupId: "uuid2", topicName: "consumer-inbox") {
41
+ domainObject {
42
+ field
43
+ }
44
+ }
45
+ }
46
+ QUERY
47
+ )
48
+ end
49
+ ```
50
+
51
+ #### Self-Serve (soft-deprecated)
52
+
53
+ You create these subscriptions via the public GraphQL API. For testing, the [Insomnia](https://insomnia.rest/) client
54
+ is highly recommended.
55
+
56
+ ```graphql
57
+ subscription {
58
+ workOrderUpdated(subscriptionId: "uuid", subscriptionGroupId: "uuid", topicName: "some-topic") {
59
+ workOrder {
60
+ id
61
+ code
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ These subscriptions are written to the `NulogyMessageBusProducer.subscriptions_table_name` table.
68
+
69
+ This style of subscriptions may be removed in a future release.
70
+
71
+ There is a [guide to migrate from Self-Serve to Configured](docs/self_serve_to_configured_subscriptions.md)
19
72
 
20
73
  ## Configuration
21
74
 
22
- | Configuration | Default | Description |
23
- |--------------------------------|---------------------------------|---------------------------------------------------------------------------------------------|
24
- | context_for_subscription | `->(_subscription) { {} }` | A lambda used to inject any GraphQL Context to be used when producing subscription events |
25
- | producing_events_fails_with | :raise | How the producer should handle errors when producing subscription events |
26
- | subscriptions_table_name | "message_bus_subscriptions" | The name of the table for the Subscription model |
27
- | subscription_events_table_name | "message_bus_subscription_events" | The name of the table for the SubscriptionEvents model |
75
+ | Configuration | Default | Description |
76
+ |--------------------------------|-----------------------------------|----------------------------------------------------------------------------------------------------|
77
+ | context_for_subscription | `->(_subscription) { {} }` | A lambda used to inject any GraphQL Context to be used when producing subscription events |
78
+ | producing_events_fails_with | :raise | How the producer should handle errors when producing subscription events |
79
+ | subscriptions_table_name | "message_bus_subscriptions" | The name of the table for the SelfServeSubscription model |
80
+ | subscription_events_table_name | "message_bus_subscription_events" | The name of the table for the SubscriptionEvents model |
81
+ | add_subscription! | [] (i.e. empty) | Add a subscription via configuration. It will supercede any configured via GraphQL for a given id. |
28
82
 
29
83
  ## Setup
30
84
 
31
85
  You should configure the gem with an initializer. A recommended setup:
32
86
 
33
87
  ```ruby
34
- # Table names are configurable (optional)
35
- NulogyMessageBusProducer.subscriptions_table_name = :message_bus_subscriptions
36
- NulogyMessageBusProducer.subscription_events_table_name = :message_bus_subscription_events
88
+ # (optional) Table names are configurable
89
+ # NulogyMessageBusProducer.subscriptions_table_name = :message_bus_subscriptions
90
+ # NulogyMessageBusProducer.subscription_events_table_name = :message_bus_subscription_events
37
91
 
38
92
  # Register known schemas
39
93
  NulogyMessageBusProducer.configure do |config|
@@ -79,11 +133,6 @@ module ExampleDomainPublicApi
79
133
  class Schema < GraphQL::Schema
80
134
  use NulogyMessageBusProducer::Subscriptions::PostgresTransport
81
135
 
82
- # You must use the Interpreter, as it will be the new default.
83
- # See more here: https://graphql-ruby.org/queries/interpreter
84
- use GraphQL::Analysis::AST
85
- use GraphQL::Execution::Interpreter
86
-
87
136
  # This prevents subscriptions which contain arguments or expand lists form being registered.
88
137
  # Expanding unbounded lists inside of an event may severely impact the performance of the system.
89
138
  # Arguments are a source of variation that may not be appropriately tested.
@@ -223,3 +272,14 @@ docker-compose up
223
272
  rake db:setup
224
273
  rake
225
274
  ```
275
+
276
+ # Gem Releases
277
+
278
+ You must be listed as a gem owner [on rubygems](https://rubygems.org/gems/nulogy_message_bus_producer) to cut a release:
279
+
280
+ * Merge your changes to `master`
281
+ * Commit a version bump
282
+ * Update `lib/nulogy_message_bus_producer/version.rb`
283
+ * Run `bundle install`
284
+ * Update the CHANGELOG
285
+ * Run `bundle exec rake release`
data/Rakefile CHANGED
@@ -13,11 +13,9 @@ require "rspec/core/rake_task"
13
13
 
14
14
  RSpec::Core::RakeTask.new(:spec)
15
15
 
16
- require "rubocop/rake_task"
16
+ require "standard/rake"
17
17
 
18
- RuboCop::RakeTask.new
19
-
20
- task default: [:spec, :rubocop]
18
+ task default: %i[spec standard]
21
19
 
22
20
  require "rake/release"
23
21
 
@@ -5,7 +5,7 @@ class CreatePublicSubscriptionsAndEventsTables < ActiveRecord::Migration[5.2]
5
5
 
6
6
  create_table NulogyMessageBusProducer.subscriptions_table_name, id: :uuid, default: nil do |t|
7
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" }
8
+ t.string :event_type, null: false, index: {name: "index_nulogy_mb_producer_subscriptions_on_event_type"}
9
9
  t.string :topic_name, null: false
10
10
  t.string :query, null: false
11
11
  t.text :schema_key, null: false
@@ -19,7 +19,7 @@ class CreatePublicSubscriptionsAndEventsTables < ActiveRecord::Migration[5.2]
19
19
  t.string :topic_name, null: false
20
20
  t.uuid :tenant_id, null: false
21
21
  t.json :event_json, null: false
22
- t.column :created_at, :datetime, index: { name: "index_nulogy_mb_producer_subscription_events_on_created_at" }
22
+ t.column :created_at, :datetime, index: {name: "index_nulogy_mb_producer_subscription_events_on_created_at"}
23
23
  end
24
24
  end
25
25
  end
@@ -1,6 +1,8 @@
1
1
  require "graphql"
2
+ require "pp"
2
3
 
3
4
  require "nulogy_message_bus_producer/config"
5
+ require "nulogy_message_bus_producer/configuration/query_parser"
4
6
  require "nulogy_message_bus_producer/version"
5
7
  require "nulogy_message_bus_producer/engine"
6
8
 
@@ -14,11 +16,11 @@ module NulogyMessageBusProducer
14
16
  end
15
17
 
16
18
  def self.subscriptions_table_name=(table_name)
17
- NulogyMessageBusProducer::Subscription.table_name = table_name
19
+ NulogyMessageBusProducer::SelfServeSubscription.table_name = table_name
18
20
  end
19
21
 
20
22
  def self.subscriptions_table_name
21
- NulogyMessageBusProducer::Subscription.table_name
23
+ NulogyMessageBusProducer::SelfServeSubscription.table_name
22
24
  end
23
25
 
24
26
  def self.subscription_events_table_name=(table_name)
@@ -35,7 +37,7 @@ module NulogyMessageBusProducer
35
37
 
36
38
  def self.trigger_event(schema, event_type, root_object)
37
39
  schema_key = NulogyMessageBusProducer.resolve_schema_key(schema)
38
- subscriptions = Subscription.where(event_type: event_type, schema_key: schema_key)
40
+ subscriptions = Subscriptions::Finder.new(config).for_schema_event(schema_key, event_type)
39
41
 
40
42
  subscriptions.each do |subscription|
41
43
  args = {
@@ -65,7 +67,9 @@ module NulogyMessageBusProducer
65
67
  end
66
68
 
67
69
  def self.resolve_schema_key(schema)
68
- config.registered_schemas.invert.fetch(schema.name) do
70
+ schema_name = schema.respond_to?(:name) ? schema.name : schema
71
+
72
+ config.registered_schemas.invert.fetch(schema_name) do
69
73
  raise KeyError, <<~MESSAGE
70
74
  The schema registry did not contain an entry for the schema '#{schema.name}'.
71
75
 
@@ -80,7 +84,7 @@ module NulogyMessageBusProducer
80
84
  def self.validate_existing!
81
85
  return unless Db.exists? && Db.subscriptions_exist?
82
86
 
83
- validator = NulogyMessageBusProducer::SubscriberGraphqlSchemaValidator.new
87
+ validator = NulogyMessageBusProducer::Subscriptions::QueryValidator.new
84
88
 
85
89
  return if validator.validate
86
90
 
@@ -136,10 +140,13 @@ end
136
140
 
137
141
  require "nulogy_message_bus_producer/application_record"
138
142
  require "nulogy_message_bus_producer/base_subscription"
139
- require "nulogy_message_bus_producer/subscription"
140
143
  require "nulogy_message_bus_producer/subscription_event"
141
144
  require "nulogy_message_bus_producer/repopulate_replication_slots"
142
- require "nulogy_message_bus_producer/subscriber_graphql_schema_validator"
143
- require "nulogy_message_bus_producer/subscriptions/postgres_transport"
145
+ require "nulogy_message_bus_producer/subscriptions/finder"
144
146
  require "nulogy_message_bus_producer/subscriptions/no_variables"
147
+ require "nulogy_message_bus_producer/subscriptions/postgres_transport"
148
+ require "nulogy_message_bus_producer/subscriptions/query_validator"
149
+ require "nulogy_message_bus_producer/subscriptions/valid_for_schema_validator"
150
+ require "nulogy_message_bus_producer/subscriptions/configured_subscription"
151
+ require "nulogy_message_bus_producer/self_serve_subscription"
145
152
  require "nulogy_message_bus_producer/subscriptions/risky_subscription_blocker"
@@ -2,7 +2,7 @@ module NulogyMessageBusProducer
2
2
  # This base class contains the fields required to create a subscription.
3
3
  # For example, for a subscription to a model called AggregateRoot:
4
4
  #
5
- # class AggregateRootCreated < NulogyMessageBusProducer::BasePublicSubscription
5
+ # class AggregateRootCreated < NulogyMessageBusProducer::BaseSubscription
6
6
  # field :aggregate_root, Domain::Public::Types::AggregateRootType, null: true
7
7
  # end
8
8
  class BaseSubscription < GraphQL::Schema::Subscription
@@ -1,14 +1,16 @@
1
1
  module NulogyMessageBusProducer
2
2
  # Configuration for the gem
3
- # This is a private class, so do not use it directly. Use the methods on NulogyMessageBusProducer.
4
3
  class Config
5
4
  FAILURE_MODES = [:raise, :soft_fail].freeze
6
5
 
7
6
  attr_reader :registered_schemas
7
+ attr_reader :configured_subscriptions
8
8
  attr_writer :context_for_subscription
9
9
 
10
10
  def initialize(options = {})
11
11
  @registered_schemas = {}
12
+ @configured_subscriptions = []
13
+
12
14
  producing_events_fails_with(:raise)
13
15
 
14
16
  update(options)
@@ -48,6 +50,28 @@ module NulogyMessageBusProducer
48
50
  options.each { |key, value| public_send("#{key}=", value) }
49
51
  end
50
52
 
53
+ def add_subscription!(schema:, query:)
54
+ @configured_subscriptions ||= []
55
+
56
+ schema_key = NulogyMessageBusProducer.resolve_schema_key(schema)
57
+ query_parser = Configuration::QueryParser.new(query)
58
+ subscription = Subscriptions::ConfiguredSubscription.new(
59
+ id: query_parser.subscription_id,
60
+ subscription_group_id: query_parser.subscription_group_id,
61
+ schema_key: schema_key,
62
+ event_type: query_parser.event_type,
63
+ topic_name: query_parser.topic,
64
+ query: query
65
+ )
66
+
67
+ if subscription.valid?
68
+ @configured_subscriptions << subscription
69
+ subscription
70
+ else
71
+ raise ArgumentError, subscription.errors.full_messages
72
+ end
73
+ end
74
+
51
75
  private
52
76
 
53
77
  def raise_handler(subscription_id:, context:, variables:, result:)
@@ -0,0 +1,71 @@
1
+ module NulogyMessageBusProducer
2
+ module Configuration
3
+ class QueryParser
4
+ class ParseError < StandardError
5
+ attr_reader :source_error
6
+
7
+ def intialize(source_error)
8
+ @source_error = source_error
9
+ end
10
+ end
11
+
12
+ def initialize(query)
13
+ @query = query
14
+ end
15
+
16
+ def subscription_id
17
+ parse
18
+
19
+ argument("subscriptionId")
20
+ rescue => e
21
+ error("subscriptionId", e)
22
+ end
23
+
24
+ def subscription_group_id
25
+ parse
26
+
27
+ argument("subscriptionGroupId")
28
+ rescue => e
29
+ error("subscriptionGroupId", e)
30
+ end
31
+
32
+ def event_type
33
+ parse
34
+
35
+ first_selection.name
36
+ rescue => e
37
+ error("event type", e)
38
+ end
39
+
40
+ def topic
41
+ parse
42
+
43
+ argument("topicName")
44
+ rescue => e
45
+ error("topic", e)
46
+ end
47
+
48
+ private
49
+
50
+ def parse
51
+ @gql ||= GraphQL::Language::Parser.parse(@query)
52
+ end
53
+
54
+ def argument(field)
55
+ first_selection
56
+ .arguments.detect { |e| e.name == field }
57
+ .value
58
+ end
59
+
60
+ def first_selection
61
+ @gql
62
+ .definitions.first
63
+ .selections.first
64
+ end
65
+
66
+ def error(field, err)
67
+ raise ParseError.new(err), "Error extracting #{field} from the subscription"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,18 @@
1
+ module NulogyMessageBusProducer
2
+ # This model saves self-serve 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 SelfServeSubscription < ApplicationRecord
5
+ self.table_name = :message_bus_subscriptions
6
+
7
+ validates :id, presence: true
8
+ validates :subscription_group_id, presence: true
9
+ validates :schema_key, :event_type, presence: true
10
+ validates :query, :presence => true, "nulogy_message_bus_producer/subscriptions/valid_for_schema" => true
11
+
12
+ def self.create_or_update(attrs)
13
+ find_or_initialize_by(id: attrs[:id]).tap do |model|
14
+ model.update!(attrs)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module NulogyMessageBusProducer
2
+ module Subscriptions
3
+ class ConfiguredSubscription
4
+ include ActiveModel::Model
5
+
6
+ attr_accessor :id, :subscription_group_id, :schema_key, :event_type, :query, :topic_name
7
+
8
+ validates :id, presence: true
9
+ validates :subscription_group_id, presence: true
10
+ validates :schema_key, :event_type, presence: true
11
+ validates :query, :presence => true, "nulogy_message_bus_producer/subscriptions/valid_for_schema" => true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ module NulogyMessageBusProducer
2
+ module Subscriptions
3
+ # A facade to find subscriptions.
4
+ #
5
+ # It will retrieve subscriptions from these sources:
6
+ # - configured subscriptions via #add_subscription!
7
+ # - self-serve subscriptions via GraphQL API
8
+ #
9
+ # If a subscription exists with the same id in both sources, then
10
+ # the configured subscription will be returned.
11
+ class Finder
12
+ def initialize(config)
13
+ @config = config
14
+ end
15
+
16
+ # Note: raises like ActiveRecord#find
17
+ def find(id)
18
+ @config.configured_subscriptions.detect { |s| s.id == id } || SelfServeSubscription.find(id)
19
+ end
20
+
21
+ def for_schema_event(schema_key, event_type)
22
+ subscriptions = configured(schema_key, event_type) + self_serve(schema_key, event_type)
23
+
24
+ subscriptions.uniq(&:id)
25
+ end
26
+
27
+ private
28
+
29
+ def self_serve(schema_key, event_type)
30
+ SelfServeSubscription.where(event_type: event_type, schema_key: schema_key)
31
+ end
32
+
33
+ def configured(schema_key, event_type)
34
+ @config
35
+ .configured_subscriptions
36
+ .filter { |s| s.event_type == event_type && s.schema_key == schema_key }
37
+ end
38
+ end
39
+ end
40
+ end