maitredee 0.8.2 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61c90edbaf57c2a995ee3f92ee780235bb8af4421a446fa9bd10286101c80949
4
- data.tar.gz: d118a9ee6cf0d03b22e46bdb8d271930ec444806a6aac071e27d496b1d952d22
3
+ metadata.gz: 52dd1ef33db5eadd01dc66f0c26f37a7ac8b5d19bfe865ec0cae03535900fedb
4
+ data.tar.gz: d0b9a43bb7eab1208fd2ff3ba5668a65d2fb870d755cbd61fb41d84274e53521
5
5
  SHA512:
6
- metadata.gz: 024331eff27c916156ad6d878647e527a8fa50da23b451f8fe853b18e4b73b481bb6e65cf0dbd385dfd151b9b7d0f15c2d194a2c4ec16b36f6c3d59566b93334
7
- data.tar.gz: 28b6af8d263162cb2ea0eff4bccb46671f5ccd173d7251fa2429c3d637aaec9ce643f993f1678d9c70738c71a78a6b20182327f879eb0d36c39d336a2c122185
6
+ metadata.gz: 24dd10b8944d88da64c2386e3660aa1cb1263523aa7e8ed0fa5ccfd430af698b787c49de230b8a8e9f402330a74e5de284bf5b9abb2fb5773e04a87f4136283d
7
+ data.tar.gz: 6e4ee09a3a305a2640bfb354031ae0000a121dba80c3bc303e7f8d68898ad234231757a3d7e1d6eb87afba2417e377e4547f66c5bc13de933f38aa1c76c4c15c
data/.circleci/config.yml CHANGED
@@ -51,11 +51,23 @@ jobs:
51
51
  - run:
52
52
  name: run rspec tests
53
53
  command: |
54
- bundle exec rspec --format progress
54
+ mkdir /tmp/test-results
55
+ bundle exec rspec \
56
+ --profile 10 \
57
+ --format progress
55
58
  - run:
56
59
  name: run sns/sqs tests
57
60
  command: |
58
61
  INTEGRATION_TEST=sns_sqs bundle exec rspec --format progress
62
+ - run:
63
+ name: run doctests
64
+ command: bundle exec goodread-rb README.md
65
+ # Collect reports
66
+ - store_test_results:
67
+ path: /tmp/test-results
68
+ - store_artifacts:
69
+ path: /tmp/test-results
70
+ destination: test-results
59
71
  workflows:
60
72
  version: 2
61
73
  build_and_test:
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup=markdown
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- maitredee (0.8.2)
4
+ maitredee (0.8.3)
5
5
  activesupport
6
6
  aws-sdk-sns
7
7
  aws-sdk-sqs
@@ -34,8 +34,8 @@ GEM
34
34
  minitest (~> 5.1)
35
35
  tzinfo (~> 1.1)
36
36
  aws-eventstream (1.0.1)
37
- aws-partitions (1.122.0)
38
- aws-sdk-core (3.44.0)
37
+ aws-partitions (1.127.0)
38
+ aws-sdk-core (3.44.1)
39
39
  aws-eventstream (~> 1.0)
40
40
  aws-partitions (~> 1.0)
41
41
  aws-sigv4 (~> 1.0)
@@ -50,6 +50,7 @@ GEM
50
50
  builder (3.2.3)
51
51
  byebug (10.0.2)
52
52
  coderay (1.1.2)
53
+ colorize (0.8.1)
53
54
  concurrent-ruby (1.1.3)
54
55
  crass (1.0.4)
55
56
  diff-lcs (1.3)
@@ -57,8 +58,12 @@ GEM
57
58
  ecma-re-validator (0.2.0)
58
59
  regexp_parser (~> 1.2)
59
60
  erubi (1.7.1)
61
+ gemoji (3.0.0)
60
62
  globalid (0.4.1)
61
63
  activesupport (>= 4.2.0)
64
+ goodread (0.3.2)
65
+ colorize (~> 0.8)
66
+ gemoji (~> 3.0)
62
67
  hana (1.3.4)
63
68
  i18n (1.1.1)
64
69
  concurrent-ruby (~> 1.0)
@@ -128,6 +133,7 @@ DEPENDENCIES
128
133
  activejob
129
134
  bundler (~> 1.17)
130
135
  dotenv
136
+ goodread
131
137
  maitredee!
132
138
  pry
133
139
  pry-byebug
@@ -137,4 +143,4 @@ DEPENDENCIES
137
143
  rspec-mocks (~> 3.0)
138
144
 
139
145
  BUNDLED WITH
140
- 1.17.1
146
+ 1.17.2
data/README.md CHANGED
@@ -1,8 +1,26 @@
1
1
  # Maitredee
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/maitredee`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ An opinionated pub/sub framework.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ ## Table of Contents
6
+ - [Overview](#overview)
7
+ - [Installation](#installation)
8
+ - [Configuration](#configuration)
9
+ - [Publisher](#publisher)
10
+ - [Subscriber](#subscriber)
11
+ - [Validation schema](#validation-schema)
12
+ - [Misc](#misc)
13
+ - [Development](#development)
14
+ - [Contributing](#contributing)
15
+ - [License](#license)
16
+ - [Code of Conduct](#code-of-conduct)
17
+
18
+ ## Overview
19
+ We made maitredee to simplify publishing and subscribing to events for our junior developers. We tried using kafka but ordered eventing was too complicated.
20
+
21
+ We tried to have zero setup required to get this up and running and make it work as simply as sidekiq.
22
+
23
+ We hope in the future to add more adapters beyond sns/sqs.
6
24
 
7
25
  ## Installation
8
26
 
@@ -20,30 +38,169 @@ Or install it yourself as:
20
38
 
21
39
  $ gem install maitredee
22
40
 
23
- ## Usage
41
+ ## Configuration
42
+
43
+ Required Configuration
44
+ ```ruby
45
+ Maitredee.namespace = "plated-production"
46
+ Maitredee.schema_path = Rails.root.join("your/path").to_s
47
+ Maitredee.client = :sns_sqs
48
+ ```
49
+
50
+ These namespace can also be set with the environment variable `MAITREDEE_NAMESPACE`
51
+
52
+ ### Available clients
53
+
54
+ Maitredee currently supports the following clients:
55
+
56
+ #### SNS/SQS :sns_sqs
57
+ You can set the AWS parameters in a variety of ways.
58
+ Either environment variables or explicitly.
59
+ Supported environment variables are `MAITREDEE_AWS_ACCESS_KEY_ID`, `MAITREDEE_AWS_SECRET_ACCESS_KEY`, `MAITREDEE_AWS_REGION` and then falls back to default AWS keys.
60
+
61
+ if you wish to set it explicitly:
62
+ ```ruby
63
+ Maitredee.set_client(
64
+ :sns_sqs,
65
+ access_key_id: "",
66
+ secret_access_key: "",
67
+ region: ""
68
+ )
69
+ ```
70
+
71
+ #### Test :test
72
+
73
+ This is used for testing.
74
+
75
+ ```ruby
76
+ Maitredee.client = :test
77
+ ```
78
+
79
+ When you pubish anything through Maitredee it will be logged in the test client for test verification.
80
+
81
+ You should reset the client at the beginning of every test with `Maitredee.client.reset`
82
+
83
+ ## Publisher
84
+
85
+ Create a publisher class for your topic and inherit from `Maitredee::Publisher`
86
+ Optionally define the default topic, event_name, or validation schema with `publish_defaults`
87
+ Maitredee will call `process` on your publisher when it is called. Define a method `process` that calls `publish` with the parameters of your choosing. `Publish` will default the `topic`, `event_name`, and `schema_name` from your publish_defaults if not given.
88
+
89
+ ```ruby goodread
90
+ require "maitredee"
91
+
92
+ class MyPublisher < Maitredee::Publisher
93
+ publish_defaults(
94
+ topic_name: :your_default_topic,
95
+ event_name: :your_default_event_name,
96
+ schema_name: :your_default_schema
97
+ )
98
+
99
+ attr_reader :model
100
+
101
+ def initialize(model)
102
+ @model = model
103
+ end
104
+
105
+ def process
106
+ publish(
107
+ topic_name: :my_topic,
108
+ event_name: :event_name_is_optional,
109
+ schema_name: :schema_name,
110
+ primary_key: "optionalKey",
111
+ body: {
112
+ id: model.id,
113
+ name: model.name
114
+ }
115
+ )
116
+ end
117
+ end
118
+ ```
119
+
120
+
121
+ ### Publishing a message
122
+ To publish a message, simply call `call` on your publisher:
123
+ ```ruby
124
+ MyPublisher.call(model)
125
+ ```
126
+
127
+ Publish will first validate your schema before publishing the message.
128
+
129
+ If you have ActiveJob you can also `#call_later` and it will be called asyncronously
130
+
131
+ ## Subscriber
132
+
133
+ ```ruby
134
+ class RecipeSubscriber < Maitredee::Subscriber
135
+ # this is the topic name
136
+ subscribe_to :recipes do
24
137
 
25
- TODO: Write usage instructions here
138
+ # this is the event name optionally say which method to use to process
139
+ event(:create, to: create)
26
140
 
27
- ## Todo
141
+ # event_name will be used as the method name if it is a valid method name, otherwise to: must be set
142
+ event(:delete)
143
+
144
+ # for empty event name just use nil
145
+ event(nil, to: :process)
146
+
147
+ # you can specify a catch all route
148
+ default_event to: :process
149
+ end
150
+
151
+ def create
152
+ Recipe.create!(message.body)
153
+ end
154
+
155
+ def process
156
+ Recipe.find(message.body[:id]).update(message.body)
157
+ end
158
+
159
+ def delete
160
+ Recipe.find(message.body[:id]).destroy
161
+ end
162
+ end
163
+ ```
164
+
165
+ ## Validating Schemas
166
+ Maitredee validates your message body schemas using JSON schema ([JSON-schemer] (https://github.com/davishmcclurg/json_schemer)) for both publishing and consuming messages. [Configure] (#configuration) the location of your schemas and provide a JSON file for each of your schemas.
167
+
168
+ Example `recipe_v1.json`:
169
+ ```json
170
+ {
171
+ "type": "object",
172
+ "required": ["id", "name", "servings"],
173
+ "properties": {
174
+ "id": {
175
+ "type": "string"
176
+ },
177
+ "name": {
178
+ "type": "string"
179
+ },
180
+ "servings": {
181
+ "type": "number"
182
+ }
183
+ }
184
+ }
185
+
186
+ ```
28
187
 
29
- * split into publisher/subscriber sub gems with monorepo
30
- * subscriber schema validation
31
- * maitredee/test helper methods for subscribers
188
+ ## Misc
32
189
 
33
- ## Development
190
+ ### Development
34
191
 
35
192
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
36
193
 
37
194
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
38
195
 
39
- ## Contributing
196
+ ### Contributing
40
197
 
41
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/maitredee. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
198
+ Bug reports and pull requests are welcome on GitHub at https://github.com/plated/maitredee. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
42
199
 
43
- ## License
200
+ ### License
44
201
 
45
202
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
46
203
 
47
- ## Code of Conduct
204
+ ### Code of Conduct
48
205
 
49
- Everyone interacting in the Maitredee project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/maitredee/blob/master/CODE_OF_CONDUCT.md).
206
+ Everyone interacting in the Maitredee project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/plated/maitredee/blob/master/CODE_OF_CONDUCT.md).
data/lib/maitredee.rb CHANGED
@@ -9,15 +9,34 @@ require "pathname"
9
9
  require "maitredee/publisher"
10
10
  require "maitredee/subscriber"
11
11
  require "maitredee/version"
12
+ require "maitredee/adapters/base_adapter"
12
13
  require "maitredee/adapters/sns_sqs_adapter"
13
14
  require "maitredee/railtie" if defined? ::Rails::Railtie
14
15
 
15
16
  module Maitredee
16
17
  class << self
17
- attr_accessor :resource_name_suffix, :schema_path
18
+
19
+ # allows you to add a suffix to all your resource names, mostly used for testing but could be useful in other occassions.
20
+ # @return [String] string appended to all resource names
21
+ attr_accessor :resource_name_suffix
22
+
23
+ # this is the path of the folder in which validation_schema will try to do a lookup. This folder should contain json schemas.
24
+ # @return [String] path to folder
25
+ attr_accessor :schema_path
26
+
27
+ # the client we use for publishing and setting up workers
28
+ # @return [Maitredee::Adapters::AbstractAdapter]
18
29
  attr_reader :client
19
- attr_writer :app_name, :namespace
20
30
 
31
+ # publishes messages using configured adapter
32
+ #
33
+ # @param topic [String] topic name
34
+ # @param body [Hash, Array, String] Any valid json data that can be validated by json-schema
35
+ # @param schema_name [String] A valid schema name for publishing data
36
+ # @param event_name [String, nil] Event name for subscriber routing
37
+ # @param primary_key [#to_s, nil] Key to be used for resource identification
38
+ #
39
+ # @return [PublisherMessage] published message
21
40
  def publish(
22
41
  topic_name:,
23
42
  body:,
@@ -44,15 +63,26 @@ module Maitredee
44
63
  message
45
64
  end
46
65
 
66
+ # configure the adapter, must be executed before loading subscribers
67
+ #
68
+ # @param slug [#to_s] name of adapter
69
+ # @param args [] options to send to the adapter
47
70
  def set_client(slug, *args)
48
71
  raise "No client set for Maitredee" if slug.nil?
49
72
  @client = "::Maitredee::Adapters::#{slug.to_s.camelize}Adapter".constantize.new(*args)
50
73
  end
51
74
 
75
+ # set a client without parameters
76
+ #
77
+ # @param slug [#to_s] name of adapter
52
78
  def client=(slug)
53
79
  set_client(slug)
54
80
  end
55
81
 
82
+ # build topic resource name from topic name
83
+ #
84
+ # @param topic_name [#to_s] topic name
85
+ # @return [String]
56
86
  def topic_resource_name(topic_name)
57
87
  [
58
88
  namespace,
@@ -61,6 +91,11 @@ module Maitredee
61
91
  ].compact.join("--")
62
92
  end
63
93
 
94
+ # build queue resource name from queue name and topic name
95
+ #
96
+ # @param topic_name [#to_s] topic name
97
+ # @param queue_name [#to_s] queue name
98
+ # @return [String]
64
99
  def queue_resource_name(topic_name, queue_name)
65
100
  [
66
101
  namespace,
@@ -75,6 +110,13 @@ module Maitredee
75
110
  end
76
111
  end
77
112
 
113
+ # validate a body given a schema name
114
+ #
115
+ # @param body [Array, Hash, String] data to send with message
116
+ # @param schema [String] string key to look up schema to validate against
117
+ #
118
+ # @raise [ValidationError] if validation fails
119
+ # @return [nil]
78
120
  def validate!(body, schema)
79
121
  errors = schemas[schema].validate(body.as_json)
80
122
  properties = errors.map do |error|
@@ -86,6 +128,9 @@ module Maitredee
86
128
  end
87
129
  end
88
130
 
131
+ # hash to look up schema based of schema_path
132
+ #
133
+ # @return Hash[JSONSchemer::Schema::Draft7]
89
134
  def schemas
90
135
  @schemas ||= Hash.new do |hash, key|
91
136
  path = Pathname.new(schema_path).join("#{key}.json")
@@ -93,6 +138,10 @@ module Maitredee
93
138
  end
94
139
  end
95
140
 
141
+ # fetch configured app name or automatically fetch from Rails or from ENV["MAITREDEE_APP_NAME"]
142
+ # used for generating queue_resource_name
143
+ #
144
+ # @return [String]
96
145
  def app_name
97
146
  @app_name ||=
98
147
  begin
@@ -106,11 +155,24 @@ module Maitredee
106
155
  end
107
156
  end
108
157
 
158
+ # set app_name instead of using default
159
+ # @param [String]
160
+ attr_writer :app_name
161
+
162
+
163
+ # fetch configured namespace or automatically fetch from ENV["MAITREDEE_NAMESPACE"]
164
+ # @return [String]
109
165
  def namespace
110
166
  @namespace ||=
111
167
  ENV["MAITREDEE_NAMESPACE"] || raise("must set namespace for maitredee")
112
168
  end
113
169
 
170
+ # set namespace instead of using default
171
+ # @param [String]
172
+ attr_writer :namespace
173
+
174
+ # idempotently configures broker to create topics, queues and subscribe queues to topics
175
+ # nothing will eveer be deleted or cleaned up
114
176
  def configure_broker
115
177
  hash_array = Hash.new { |hash, key| hash[key] = [] }
116
178
  topics_and_queues =
@@ -121,11 +183,13 @@ module Maitredee
121
183
  client.configure_broker(topics_and_queues)
122
184
  end
123
185
 
186
+ # @api private
124
187
  def register_subscriber(klass)
125
188
  client.add_worker(klass)
126
189
  subscriber_registry.add(klass)
127
190
  end
128
191
 
192
+ # @api private
129
193
  def subscriber_registry
130
194
  @subscriber_registry ||= Set.new
131
195
  end
@@ -14,6 +14,16 @@ module Maitredee
14
14
  subclass::PublisherJob.service_class = subclass
15
15
  end
16
16
 
17
+ # Uses ActieJob to async the publishing
18
+ # @example To configure the specific async job open PublisherJob
19
+ # class RecipePublisher < Maitredee::Publisher
20
+ # class PublisherJob
21
+ # queue_as :low
22
+ # end
23
+ # end
24
+ #
25
+ # RecipePublisher.call_later(Recipe.find(1))
26
+ #
17
27
  def call_later(*args)
18
28
  self::PublisherJob.perform_later(*args)
19
29
  end
@@ -0,0 +1,18 @@
1
+ module Maitredee
2
+ module Adapters
3
+ class BaseAdapter
4
+ def publish(message)
5
+ raise NotImplementedError
6
+ end
7
+
8
+ def add_worker(subscriber_class)
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def reset
13
+ raise NotImplementedError
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -3,9 +3,15 @@ require "aws-sdk-sqs"
3
3
 
4
4
  module Maitredee
5
5
  module Adapters
6
- class SnsSqsAdapter
6
+ class SnsSqsAdapter < BaseAdapter
7
7
  attr_reader :access_key_id, :secret_access_key, :region
8
8
 
9
+ # @param access_key_id [String] if `nil` will look in `ENV["MAITREDEE_AWS_ACCESS_KEY_ID"]`
10
+ # @param secret_access_key [String] if `nil` will look in `ENV["MAITREDEE_AWS_SECRET_ACCESS_KEY"]`
11
+ # @param region [String] if `nil` will look in `ENV["MAITREDEE_AWS_REGION"]`
12
+ # @param default_shoryuken_options [Hash] default options of the shoryuken job listening to the queues
13
+ # defaults to `{ body_parser: :json, auto_delete: true }`
14
+
9
15
  def initialize(access_key_id: nil, secret_access_key: nil, region: nil, default_shoryuken_options: nil)
10
16
  @access_key_id = access_key_id || ENV["MAITREDEE_AWS_ACCESS_KEY_ID"]
11
17
  @secret_access_key = secret_access_key || ENV["MAITREDEE_AWS_SECRET_ACCESS_KEY"]
@@ -15,6 +21,8 @@ module Maitredee
15
21
  Shoryuken.sqs_client = sqs_client
16
22
  end
17
23
 
24
+ # publishes message to SNS
25
+ # @param message [PublisherMessage]
18
26
  def publish(message)
19
27
  message_attributes = {
20
28
  message_id: message.message_id,
@@ -32,6 +40,8 @@ module Maitredee
32
40
  )
33
41
  end
34
42
 
43
+ # creates topics from keys and queues from values, and subscribes queues to topics
44
+ # @param config [Hash{String => Array<String>}]
35
45
  def configure_broker(config)
36
46
  config.each do |topic_resource_name, queue_resource_names|
37
47
  queue_resource_names.each do |queue_resource_name|
@@ -43,6 +53,7 @@ module Maitredee
43
53
  end
44
54
  end
45
55
 
56
+ # @api private
46
57
  def topics
47
58
  @topics ||= Hash.new do |hash, key|
48
59
  topic = sns_client.create_topic(
@@ -52,6 +63,7 @@ module Maitredee
52
63
  end
53
64
  end
54
65
 
66
+ # @api private
55
67
  def queues
56
68
  @queues ||= Hash.new do |hash, key|
57
69
  queue_url = sqs_client.create_queue(queue_name: key).queue_url
@@ -59,10 +71,14 @@ module Maitredee
59
71
  end
60
72
  end
61
73
 
74
+ # @api private
62
75
  def subscriptions
63
76
  @subscriptions ||= {}
64
77
  end
65
78
 
79
+ # subscribes a queue to a topic
80
+ # @param queue_resource_name [String]
81
+ # @param topic_resource_name [String]
66
82
  def subscribe(queue_resource_name:, topic_resource_name:)
67
83
  topic = topics[topic_resource_name]
68
84
  queue = queues[queue_resource_name]
@@ -102,6 +118,7 @@ module Maitredee
102
118
  worker_class
103
119
  end
104
120
 
121
+ # @api private
105
122
  def default_shoryuken_options
106
123
  @default_shoryuken_options ||= {
107
124
  body_parser: :json,
@@ -109,6 +126,8 @@ module Maitredee
109
126
  }
110
127
  end
111
128
 
129
+ # deletes all topics, queues, and subscriptions
130
+ # @api private
112
131
  def reset
113
132
  [topics, queues, subscriptions].each do |resource|
114
133
  resource.values.each(&:delete)
@@ -1,17 +1,21 @@
1
1
  module Maitredee
2
2
  module Adapters
3
- class TestAdapter
3
+ class TestAdapter < BaseAdapter
4
+ # logs message published
4
5
  def publish(message)
5
6
  messages << message
6
7
  end
7
8
 
9
+ # returns all messages that have been published since last #reset
8
10
  def messages
9
11
  @messages ||= []
10
12
  end
11
13
 
14
+ # no-op
12
15
  def add_worker(subscriber_class)
13
16
  end
14
17
 
18
+ # resets messages logged
15
19
  def reset
16
20
  messages.clear
17
21
  end
@@ -1,12 +1,37 @@
1
1
  module Maitredee
2
+ ##
3
+ # Inherit from this class to easily publish messages:
4
+ #
5
+ # class RecipePublisher < Maitredee::Publisher
6
+ #
7
+ # def initialize(recipe)
8
+ # @recipe = recipe
9
+ # end
10
+ #
11
+ # def process
12
+ # # do some work
13
+ # end
14
+ # end
15
+ #
16
+ # Then in your Rails app, you can do this:
17
+ #
18
+ # RecipePublisher.call(1, 2, 3)
19
+ #
20
+ # Note that `call` is a class method, `process` is an instance method.
2
21
  class Publisher
3
22
  class << self
23
+ # call #process and return publishes messages
24
+ # @param args [] arguments passed to #initialize
4
25
  def call(*args)
5
26
  publisher = new(*args)
6
27
  publisher.process
7
28
  publisher.published_messages
8
29
  end
9
30
 
31
+ # set publish defaults
32
+ # @param topic_name [#to_s, nil]
33
+ # @param event_name [#to_s, nil]
34
+ # @param schema_name [#to_s, nil]
10
35
  def publish_defaults(topic_name: nil, event_name: nil, schema_name: nil)
11
36
  @publish_defaults = {
12
37
  topic_name: topic_name,
@@ -20,10 +45,18 @@ module Maitredee
20
45
  end
21
46
  end
22
47
 
48
+ # array of messages published in this instance
49
+ # @return [Array<PublisherMessage>]
23
50
  def published_messages
24
51
  @published_messages ||= []
25
52
  end
26
53
 
54
+ # publish a message with defaults
55
+ # @param topic_name [#to_s, nil]
56
+ # @param event_name [#to_s, nil]
57
+ # @param schema_name [#to_s, nil]
58
+ # @param primary_key [#to_s, nil]
59
+ # @param body [#to_json]
27
60
  def publish(topic_name: nil, event_name: nil, schema_name: nil, primary_key: nil, body:)
28
61
  defaults = self.class.get_publish_defaults
29
62
  published_messages << Maitredee.publish(
@@ -1,11 +1,28 @@
1
1
  require "shoryuken"
2
2
 
3
3
  module Maitredee
4
+ ##
5
+ # Inherit from this class to easily subscrive to messages:
6
+ #
7
+ # class RecipeSubscriber < Maitredee::Subscriber
8
+ # subscribe_to :recipes do
9
+ # event(:update) # by default this calls the event_name, #delete
10
+ # end
11
+ #
12
+ # def update
13
+ # # do some work
14
+ # end
15
+ # end
16
+ #
17
+ # If you want to process a message manually
18
+ #
19
+ # RecipePublisher.process()
20
+ #
21
+ # Note that `call` is a class method, `process` is an instance method.
4
22
  class Subscriber
5
23
  EventConfig = Struct.new(
6
24
  :action,
7
25
  :event_name,
8
- :minimum_schema,
9
26
  keyword_init: true
10
27
  )
11
28
 
@@ -16,25 +33,33 @@ module Maitredee
16
33
  @subscriber = subscriber
17
34
  end
18
35
 
19
- def event(event_name, to: nil, minimum_schema: nil)
36
+ # configure subscriber to listen to event_name
37
+ # @param event_name [nil, #to_s]
38
+ # @param to [#to_s] must be valid method name
39
+ def event(event_name, to: nil)
20
40
  if event_name.nil? && to.nil?
21
41
  raise ArgumentError, "event_name and to: cannot both be nil"
22
42
  end
23
43
 
44
+ if event_name.present? && /[@$"]/ =~ event_name.to_sym.inspect && to.nil?
45
+ raise ArgumentError, "'#{event_name}' is not a valid method name, you must set the 'to' parameter"
46
+ end
47
+
24
48
  event_config = EventConfig.new(
25
49
  event_name: event_name.to_s,
26
- action: (to || event_name).to_s,
27
- minimum_schema: minimum_schema
50
+ action: (to || event_name).to_s
28
51
  )
29
52
 
30
53
  subscriber.event_configs[event_config.event_name] = event_config
31
54
  end
32
55
 
33
- def default_event(to:, minimum_schema: nil)
56
+ # configure a default method to be called if not specifically configured to be listened to
57
+ # @param event_name [#to_s]
58
+ # @param to [#to_sym] must be valid method name
59
+ def default_event(to:)
34
60
  subscriber.event_configs.default = EventConfig.new(
35
61
  event_name: nil,
36
- action: to.to_s,
37
- minimum_schema: minimum_schema
62
+ action: to.to_s
38
63
  )
39
64
  end
40
65
  end
@@ -42,6 +67,30 @@ module Maitredee
42
67
  class << self
43
68
  attr_reader :topic_name
44
69
 
70
+ # configures Subscriber to which topic it should listen to and lets you configure events in the block
71
+ # @example subscribe to a topic
72
+ # class RecipeSubscriber < Maitredee::Subscriber
73
+ # subscribe_to :recipes do
74
+ # event(:delete) # by default this calls the event_name, #delete
75
+ # event(:update, to: :process) # events can be routed to different methods though
76
+ # event(nil, to: :process) # subscribe without event names
77
+ #
78
+ # default_event(to: :process) # this will default a catch all route
79
+ # end
80
+ #
81
+ # def delete
82
+ # # do some work
83
+ # end
84
+ #
85
+ # def process
86
+ # # do some work
87
+ # end
88
+ # end
89
+ #
90
+ # @see SubscriberProxy
91
+ # @param topic_name [#to_s]
92
+ # @param queue_name [#to_s] overide default generation from class name
93
+ # @param queue_resource_name [#to_s] overide default generation from queue_name and topic_name
45
94
  def subscribe_to(topic_name, queue_name: nil, queue_resource_name: nil, &block)
46
95
  @topic_name = topic_name
47
96
  @queue_name = queue_name if queue_name
@@ -57,18 +106,24 @@ module Maitredee
57
106
  Maitredee.register_subscriber(self)
58
107
  end
59
108
 
109
+ # @api private
60
110
  def event_configs
61
111
  @event_configs ||= {}
62
112
  end
63
113
 
114
+ # returns the queue_name set in .subscribe_to or is generated off the class name without `Subscriber`
64
115
  def queue_name
65
116
  @queue_name ||= name.chomp(Subscriber.name.demodulize).underscore.dasherize
66
117
  end
67
118
 
119
+ # Returns the resource name of the queue depending on the adapter
120
+ # @return [String]
68
121
  def queue_resource_name
69
122
  @queue_resource_name ||= Maitredee.queue_resource_name(topic_name, queue_name)
70
123
  end
71
124
 
125
+ # takes message and routes it based off SubscriberMessage#event_name
126
+ # @param message [SubscriberMessage]
72
127
  def process(message)
73
128
  event_config = event_configs[message.event_name.to_s]
74
129
  if event_config
@@ -77,8 +132,10 @@ module Maitredee
77
132
  end
78
133
  end
79
134
 
135
+ # @return [SubscriberMessage]
80
136
  attr_reader :message
81
137
 
138
+ # @param message [SubscriberMessage]
82
139
  def initialize(message)
83
140
  @message = message
84
141
  end
@@ -1,3 +1,3 @@
1
1
  module Maitredee
2
- VERSION = "0.8.2"
2
+ VERSION = "0.8.3"
3
3
  end
data/maitredee.gemspec CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_development_dependency "bundler", "~> 1.17"
34
34
  spec.add_development_dependency "dotenv"
35
+ spec.add_development_dependency "goodread"
35
36
  spec.add_development_dependency "pry"
36
37
  spec.add_development_dependency "pry-byebug"
37
38
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maitredee
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Plated Devs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-10 00:00:00.000000000 Z
11
+ date: 2018-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: goodread
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: pry
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -232,6 +246,7 @@ files:
232
246
  - ".gitignore"
233
247
  - ".rspec"
234
248
  - ".ruby-version"
249
+ - ".yardopts"
235
250
  - CODE_OF_CONDUCT.md
236
251
  - Gemfile
237
252
  - Gemfile.lock
@@ -243,6 +258,7 @@ files:
243
258
  - exe/maitredee
244
259
  - lib/maitredee.rb
245
260
  - lib/maitredee/active_job.rb
261
+ - lib/maitredee/adapters/base_adapter.rb
246
262
  - lib/maitredee/adapters/sns_sqs_adapter.rb
247
263
  - lib/maitredee/adapters/test_adapter.rb
248
264
  - lib/maitredee/cli/runner.rb
@@ -271,7 +287,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
287
  version: '0'
272
288
  requirements: []
273
289
  rubyforge_project:
274
- rubygems_version: 2.7.8
290
+ rubygems_version: 2.7.6
275
291
  signing_key:
276
292
  specification_version: 4
277
293
  summary: Opinionated pub/sub framework