stenotype 0.1.0 → 0.1.1
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 +4 -4
- data/.rubocop.yml +3 -2
- data/CHANGELOG.md +26 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +111 -60
- data/README.md +5 -5
- data/Rakefile +2 -2
- data/TODO.md +18 -0
- data/bin/console +3 -3
- data/lib/generators/USAGE +8 -0
- data/lib/generators/stenotype/initializer/initializer_generator.rb +23 -0
- data/lib/generators/stenotype/initializer/templates/initializer.rb.erb +65 -0
- data/lib/stenotype.rb +24 -85
- data/lib/stenotype/adapters.rb +3 -3
- data/lib/stenotype/adapters/base.rb +10 -0
- data/lib/stenotype/adapters/google_cloud.rb +53 -21
- data/lib/stenotype/adapters/stdout_adapter.rb +23 -1
- data/lib/stenotype/configuration.rb +91 -36
- data/lib/stenotype/context_handlers.rb +6 -8
- data/lib/stenotype/context_handlers/base.rb +14 -3
- data/lib/stenotype/context_handlers/collection.rb +78 -34
- data/lib/stenotype/context_handlers/rails/active_job.rb +3 -11
- data/lib/stenotype/context_handlers/rails/controller.rb +10 -11
- data/lib/stenotype/dispatcher.rb +1 -2
- data/lib/stenotype/emitter.rb +162 -0
- data/lib/stenotype/event.rb +8 -9
- data/lib/stenotype/event_serializer.rb +25 -5
- data/lib/stenotype/frameworks/rails/action_controller.rb +41 -19
- data/lib/stenotype/frameworks/rails/active_job.rb +3 -5
- data/lib/stenotype/railtie.rb +37 -0
- data/lib/stenotype/version.rb +1 -1
- data/stenotype.gemspec +30 -26
- metadata +69 -19
- data/lib/stenotype/exceptions.rb +0 -31
- data/lib/stenotype/frameworks/object_ext.rb +0 -145
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
#
|
5
|
+
# A module enclosing Rails generators for gem setup
|
6
|
+
#
|
7
|
+
module Generators
|
8
|
+
#
|
9
|
+
# A class for generating a Rails initializer to setup the gem
|
10
|
+
# upon rails application load.
|
11
|
+
#
|
12
|
+
class InitializerGenerator < Rails::Generators::Base
|
13
|
+
source_root File.expand_path("templates", __dir__)
|
14
|
+
|
15
|
+
#
|
16
|
+
# Creates an initializer for rails application
|
17
|
+
#
|
18
|
+
def create_initializer
|
19
|
+
template "initializer.rb.erb", File.join("config/initializers/stenotype.rb")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Rails.application.configure do
|
4
|
+
#
|
5
|
+
# Stenotype allows you to emit events which are then being published to a list of
|
6
|
+
# targets. Currently two targets are provided by default: Google Cloud Pub Sub and
|
7
|
+
# STDOUT for debug purposes.
|
8
|
+
#
|
9
|
+
# There is also a rails integration module which defines a handy DSL
|
10
|
+
# for triggering events in various Rails components. ActionController and
|
11
|
+
# ActiveJob are supported at the time of writing.
|
12
|
+
#
|
13
|
+
# Both extensions for Rails are enabled by default, but there are config options
|
14
|
+
# to control their presence.
|
15
|
+
# config.stenotype.rails do |rails_modules|
|
16
|
+
# rails_modules.enable_action_controller_ext = true
|
17
|
+
# rails_modules.enable_active_job_ext = true
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# To make publishing possible one must specify a list of targets. You could use
|
22
|
+
# StdoutAdapter for debug purposes before switching to a production publisher.
|
23
|
+
# By default the list of targets is empty and you'll get an error saying
|
24
|
+
# that no targets are specified.
|
25
|
+
#
|
26
|
+
# A config option is available for setting up the targets:
|
27
|
+
#
|
28
|
+
# config.stenotype.targets = [Stenotype::Adapters::StdoutAdapter.new]
|
29
|
+
#
|
30
|
+
# Or using Google Cloud:
|
31
|
+
#
|
32
|
+
# config.stenotype.targets = [Stenotype::Adapters::GoogleCloud.new]
|
33
|
+
#
|
34
|
+
# Or both:
|
35
|
+
#
|
36
|
+
# config.stenotype.targets = [
|
37
|
+
# Stenotype::Adapters::StdoutAdapter.new,
|
38
|
+
# Stenotype::Adapters::GoogleCloud.new
|
39
|
+
# ]
|
40
|
+
#
|
41
|
+
# To be able to use Google Cloud one has to specify Google Cloud credentials:
|
42
|
+
#
|
43
|
+
# config.stenotype.google_cloud do |gc_config|
|
44
|
+
# gc_config.credentials = "SPECIFY YOUR CREDENTIALS" # path/to/key.json
|
45
|
+
# gc_config.project_id = "SPECIFY YOUR PROJECT ID"
|
46
|
+
# gc_config.topic = "SPECIFY YOUR TOPIC"
|
47
|
+
# gc_config.mode = :async
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# Each event is shipped with a UUID generated with SecureRandom by default.
|
51
|
+
# This might be changed by using a corresponding config option. Note that
|
52
|
+
# uuid_generator expects method #uuid to be implemented
|
53
|
+
#
|
54
|
+
# config.stenotype.uuid_generator = SecureRandom
|
55
|
+
#
|
56
|
+
# In rare cases you might want to get control over how the event is being dispatched.
|
57
|
+
# Dispatcher must implement instance method #publish.
|
58
|
+
# Which dispatcher to use is controlled by the following config option:
|
59
|
+
#
|
60
|
+
# config.stenotype.dispatcher = Stenotype::Dispatcher
|
61
|
+
#
|
62
|
+
end
|
63
|
+
|
64
|
+
# For more usage instructions please refer to either README.md or yard documentation
|
65
|
+
# in gem repository https://github.com/Freshly/stenotype
|
data/lib/stenotype.rb
CHANGED
@@ -1,98 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# A top level namespace for the freshly-events gem
|
5
|
-
#
|
6
|
-
module Stenotype
|
7
|
-
class << self
|
8
|
-
##
|
9
|
-
# Configures the library.
|
10
|
-
# @yield {Stenotype::Configuration}
|
11
|
-
#
|
12
|
-
# @example
|
13
|
-
#
|
14
|
-
# Stenotype.configure do |config|
|
15
|
-
# config.targets = [
|
16
|
-
# Stenotype::Adapters::StdoutAdapter.new,
|
17
|
-
# Stenotype::Adapters::GoogleCloud.new
|
18
|
-
# ]
|
19
|
-
#
|
20
|
-
# config.dispatcher = Stenotype::Dispatcher.new
|
21
|
-
# config.gc_project_id = ENV['GC_PROJECT_ID']
|
22
|
-
# config.gc_credentials = ENV['GC_CREDENTIALS']
|
23
|
-
# config.gc_topic = ENV['GC_TOPIC']
|
24
|
-
# config.gc_mode = :async
|
25
|
-
# end
|
26
|
-
#
|
27
|
-
def configure(&block)
|
28
|
-
Stenotype::Configuration.configure(&block)
|
29
|
-
end
|
3
|
+
require "securerandom"
|
30
4
|
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
def config
|
35
|
-
Stenotype::Configuration
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
5
|
+
require "spicery"
|
6
|
+
require "stenotype/version"
|
39
7
|
|
40
8
|
require "stenotype/adapters"
|
9
|
+
require "stenotype/dispatcher"
|
41
10
|
require "stenotype/configuration"
|
42
11
|
require "stenotype/context_handlers"
|
43
|
-
require "stenotype/dispatcher"
|
44
12
|
require "stenotype/event"
|
45
13
|
require "stenotype/event_serializer"
|
46
|
-
require "stenotype/
|
47
|
-
require "stenotype/version"
|
48
|
-
require "stenotype/frameworks/object_ext"
|
49
|
-
|
50
|
-
Stenotype.configure do |config|
|
51
|
-
config.uuid_generator = SecureRandom
|
52
|
-
config.dispatcher = Stenotype::Dispatcher.new
|
53
|
-
|
54
|
-
config.gc_project_id = ENV['GC_PROJECT_ID']
|
55
|
-
config.gc_credentials = ENV['GC_CREDENTIALS']
|
56
|
-
config.gc_topic = ENV['GC_TOPIC']
|
57
|
-
config.gc_mode = :async
|
14
|
+
require "stenotype/emitter"
|
58
15
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
|
16
|
+
#
|
17
|
+
# A top level namespace for the freshly-events gem
|
18
|
+
#
|
19
|
+
module Stenotype
|
20
|
+
# A wrapper class for Stenotype specific errors
|
21
|
+
class Error < StandardError; end
|
22
|
+
# This exception is being raised upon unsuccessful publishing of an event.
|
23
|
+
class MessageNotPublishedError < Error; end
|
24
|
+
# This exception is being raised in case no targets are
|
25
|
+
# specified {Stenotype::Configuration}.
|
26
|
+
class NoTargetsSpecifiedError < Error; end
|
27
|
+
# This exception is being raised upon using a context handler which
|
28
|
+
# has never been registered in known handlers in {Stenotype::ContextHandlers::Collection}.
|
29
|
+
class UnknownHandlerError < Error; end
|
30
|
+
|
31
|
+
include Spicerack::Configurable::ConfigDelegation
|
32
|
+
delegates_to_configuration
|
69
33
|
end
|
70
34
|
|
71
|
-
|
72
|
-
require "stenotype/frameworks/rails/action_controller"
|
73
|
-
require "stenotype/frameworks/rails/active_job"
|
74
|
-
|
75
|
-
module Stenotype
|
76
|
-
class Railtie < Rails::Railtie # :nodoc:
|
77
|
-
config.stenotype = Stenotype.config
|
78
|
-
|
79
|
-
#
|
80
|
-
# Register Rails handlers
|
81
|
-
#
|
82
|
-
Stenotype::ContextHandlers.module_eval do
|
83
|
-
register Stenotype::ContextHandlers::Rails::Controller
|
84
|
-
register Stenotype::ContextHandlers::Rails::ActiveJob
|
85
|
-
end
|
35
|
+
Stenotype::ContextHandlers.register(Stenotype::ContextHandlers::Klass)
|
86
36
|
|
87
|
-
|
88
|
-
include Stenotype::Frameworks::Rails::ActionControllerExtension
|
89
|
-
end
|
90
|
-
|
91
|
-
ActiveSupport.on_load(:active_job) do
|
92
|
-
# @todo: consider using `::ActiveJob::Base.around_perform`
|
93
|
-
# or `::ActiveJob::Base.around_enqueue`
|
94
|
-
extend Stenotype::Frameworks::Rails::ActiveJobExtension
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
37
|
+
require "stenotype/railtie" if defined?(Rails)
|
data/lib/stenotype/adapters.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "stenotype/adapters/base"
|
4
|
+
require "stenotype/adapters/google_cloud"
|
5
|
+
require "stenotype/adapters/stdout_adapter"
|
@@ -11,6 +11,16 @@ module Stenotype
|
|
11
11
|
# An abstract base class for implementing adapters
|
12
12
|
#
|
13
13
|
# @abstract
|
14
|
+
# @example Defining a custom adapter
|
15
|
+
# MyCustomAdapter < Stenotype::Adapters::Base
|
16
|
+
# def publish(event_data, **additional_arguments)
|
17
|
+
# client.publish(event_data, **additional_arguments)
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def client
|
21
|
+
# @client ||= SomeCustomClient.new(some_credential)
|
22
|
+
# end
|
23
|
+
# end
|
14
24
|
#
|
15
25
|
class Base
|
16
26
|
attr_reader :client
|
@@ -1,55 +1,87 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "google/cloud/pubsub"
|
4
4
|
|
5
5
|
module Stenotype
|
6
6
|
module Adapters
|
7
7
|
#
|
8
8
|
# An adapter implementing method {#publish} to send data to Google Cloud PubSub
|
9
9
|
#
|
10
|
+
# @example A general usage within some method in the class
|
11
|
+
# class EventEmittingClass
|
12
|
+
# def method_emitting_enent
|
13
|
+
# result_of_calculations = collect_some_data
|
14
|
+
# gc_adapter.publish(result_of_calculation, additional: :data, more: :data)
|
15
|
+
# result_of_calculations
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def gc_adapter
|
19
|
+
# Stenotype::Adapters::GoogleCloud.new
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @example Overriding a client
|
24
|
+
# class EventEmittingClass
|
25
|
+
# def method_emitting_enent
|
26
|
+
# result_of_calculations = collect_some_data
|
27
|
+
# gc_adapter.publish(result_of_calculation, additional: :data, more: :data)
|
28
|
+
# result_of_calculations
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def gc_adapter
|
32
|
+
# Stenotype::Adapters::GoogleCloud.new(client: CustomGcClient.new)
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
#
|
10
36
|
class GoogleCloud < Base
|
11
37
|
#
|
12
38
|
# @param event_data {Hash} The data to be published to Google Cloud
|
13
|
-
# @raise {Stenotype::
|
14
|
-
#
|
15
|
-
# @
|
39
|
+
# @raise {Stenotype::MessageNotPublishedError} unless message is published
|
40
|
+
#
|
41
|
+
# @example With default client
|
42
|
+
# google_cloud_adapter = Stenotype::Adapters::GoogleCloud.new
|
43
|
+
# # publishes to default client
|
44
|
+
# google_cloud_adapter.publish({ event: :data }, { additional: :data })
|
16
45
|
#
|
17
|
-
#
|
46
|
+
# @example With client override
|
47
|
+
# google_cloud_adapter = Stenotype::Adapters::GoogleCloud.new(CustomGCClient.new)
|
48
|
+
# # publishes to default CustomGCClient
|
49
|
+
# google_cloud_adapter.publish({ event: :data }, { additional: :data })
|
18
50
|
#
|
19
51
|
def publish(event_data, **additional_arguments)
|
20
|
-
|
21
|
-
|
22
|
-
topic.publish_async(event_data, additional_arguments) do |result|
|
23
|
-
raise Stenotype::Exceptions::MessageNotPublished unless result.succeeded?
|
24
|
-
end
|
25
|
-
when :sync
|
26
|
-
topic.publish(event_data, additional_arguments)
|
52
|
+
if config.async
|
53
|
+
publish_async(event_data, **additional_arguments)
|
27
54
|
else
|
28
|
-
|
29
|
-
'Please use either :sync or :async modes for publishing the events.'
|
55
|
+
publish_sync(event_data, **additional_arguments)
|
30
56
|
end
|
31
57
|
end
|
32
|
-
# rubocop:enable Metrics/MethodLength
|
33
58
|
|
34
59
|
private
|
35
60
|
|
61
|
+
def publish_sync(event_data, **additional_arguments)
|
62
|
+
topic.publish(event_data, additional_arguments)
|
63
|
+
end
|
64
|
+
|
65
|
+
def publish_async(event_data, **additional_arguments)
|
66
|
+
topic.publish_async(event_data, additional_arguments) do |result|
|
67
|
+
raise Stenotype::MessageNotPublishedError unless result.succeeded?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
36
71
|
# :nocov:
|
37
72
|
def client
|
38
|
-
@client ||= Google::Cloud::PubSub.new(
|
39
|
-
project_id: config.gc_project_id,
|
40
|
-
credentials: config.gc_credentials
|
41
|
-
)
|
73
|
+
@client ||= Google::Cloud::PubSub.new(project_id: config.project_id, credentials: config.credentials)
|
42
74
|
end
|
43
75
|
|
44
76
|
# Use memoization, otherwise a new topic will be created
|
45
77
|
# every time. And a new async_publisher will be created.
|
46
78
|
# :nocov:
|
47
79
|
def topic
|
48
|
-
@topic ||= client.topic config.
|
80
|
+
@topic ||= client.topic config.topic
|
49
81
|
end
|
50
82
|
|
51
83
|
def config
|
52
|
-
Stenotype.config
|
84
|
+
Stenotype.config.google_cloud
|
53
85
|
end
|
54
86
|
end
|
55
87
|
end
|
@@ -5,12 +5,34 @@ module Stenotype
|
|
5
5
|
#
|
6
6
|
# An adapter implementing method {#publish} to send data to STDOUT
|
7
7
|
#
|
8
|
+
# @example
|
9
|
+
# class SomeClassWithEvents
|
10
|
+
# def method_emitting_enent
|
11
|
+
# result_of_calculations = collect_some_data
|
12
|
+
# # This will print the data to STDOUT by default
|
13
|
+
# stdout_adapter.publish(result_of_calculation, additional: :data, more: :data)
|
14
|
+
# result_of_calculations
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def stdout_adapter
|
18
|
+
# Stenotype::Adapters::StdoutAdapter.new
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
8
22
|
class StdoutAdapter < Base
|
9
23
|
#
|
10
24
|
# @param event_data {Hash} The data to be published to STDOUT
|
11
25
|
#
|
26
|
+
# @example Publishing to default client (STDOUT)
|
27
|
+
# adapter = Stenotype::Adapters::StdoutAdapter.new
|
28
|
+
# adapter.publish({ event: :data }, { additional: :data })
|
29
|
+
#
|
30
|
+
# @example Publishing to custom client (STDERR)
|
31
|
+
# adapter = Stenotype::Adapters::StdoutAdapter.new(client: STDERR)
|
32
|
+
# adapter.publish({ event: :data }, { additional: :data })
|
33
|
+
#
|
12
34
|
def publish(event_data, **additional_arguments)
|
13
|
-
client.info(event_data, **additional_arguments)
|
35
|
+
client.info(**event_data, **additional_arguments)
|
14
36
|
end
|
15
37
|
|
16
38
|
private
|
@@ -4,46 +4,101 @@ module Stenotype
|
|
4
4
|
#
|
5
5
|
# A module containing freshly-event gem configuration
|
6
6
|
#
|
7
|
+
# @example Configuring the library
|
8
|
+
# Stenotype.configure do |config|
|
9
|
+
# config.targets = [Target1.new, Target2.new]
|
10
|
+
# config.uuid_generator = SecureRandom
|
11
|
+
#
|
12
|
+
# config.google_cloud do |gc|
|
13
|
+
# gc.credentials = "abc"
|
14
|
+
# gc.project_id = "project"
|
15
|
+
# gc.topic = "42"
|
16
|
+
# gc.async = true
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# config.rails do |rc|
|
20
|
+
# rc.enable_action_controller_ext = true
|
21
|
+
# rc.enable_active_job_ext = false
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
7
25
|
module Configuration
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
extend Spicerack::Configurable
|
27
|
+
|
28
|
+
# @!attribute targets
|
29
|
+
# @return {Array<#publish>} a list of targets responding to method [#publish]
|
30
|
+
|
31
|
+
# @!attribute [rw] dispatcher
|
32
|
+
# @return {#publish} as object responding to method [#publish]
|
33
|
+
|
34
|
+
# @!attribute [rw] uuid_generator
|
35
|
+
# @return {#uuid} an object responding to method [#uuid]
|
36
|
+
|
37
|
+
# @!attribute [rw] google_cloud
|
38
|
+
# @return [NestedConfiguration] google cloud configuration.
|
39
|
+
|
40
|
+
# @!attribute [rw] google_cloud.credentials
|
41
|
+
# @return {String} a string with GC API credential. Refer to GC PubSub documentation
|
42
|
+
|
43
|
+
# @!attribute [rw] google_cloud.project_id
|
44
|
+
# @return {String} a name of the project in GC PubSub
|
45
|
+
|
46
|
+
# @!attribute [rw] google_cloud.topic
|
47
|
+
# @return {String} a name of the topic in GC PubSub
|
48
|
+
|
49
|
+
# @!attribute [rw] google_cloud.async
|
50
|
+
# @return [true, false] GC publish mode, either async if true, sync if false
|
51
|
+
|
52
|
+
|
53
|
+
# @!attribute [rw] rails
|
54
|
+
# @return [NestedConfiguration] Rails configuration.
|
55
|
+
|
56
|
+
# @!attribute [rw] rails.enable_action_controller_ext
|
57
|
+
# @return [true, false] A flag of whether ActionController ext is enabled
|
58
|
+
|
59
|
+
# @!attribute [rw] rails.enable_active_job_ext
|
60
|
+
# @return [true, false] A flag of whether ActiveJob ext is enabled
|
61
|
+
|
62
|
+
configuration_options do
|
63
|
+
option :targets, default: []
|
64
|
+
option :dispatcher, default: Stenotype::Dispatcher
|
65
|
+
option :uuid_generator, default: SecureRandom
|
66
|
+
|
67
|
+
nested :google_cloud do
|
68
|
+
option :credentials, default: nil
|
69
|
+
option :project_id, default: nil
|
70
|
+
option :topic, default: nil
|
71
|
+
option :async, default: true
|
32
72
|
end
|
33
73
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
#
|
38
|
-
def targets
|
39
|
-
if @targets.nil? || @targets.empty?
|
40
|
-
raise Stenotype::Exceptions::NoTargetsSpecified,
|
41
|
-
'Please configure a target(s) for events to be sent to. ' \
|
42
|
-
'See Stenotype::Configuration for reference.'
|
43
|
-
else
|
44
|
-
@targets
|
45
|
-
end
|
74
|
+
nested :rails do
|
75
|
+
option :enable_action_controller_ext, default: true
|
76
|
+
option :enable_active_job_ext, default: true
|
46
77
|
end
|
47
78
|
end
|
79
|
+
|
80
|
+
module_function
|
81
|
+
|
82
|
+
#
|
83
|
+
# @example When at least one target is present
|
84
|
+
# Stenotype.configure do |config|
|
85
|
+
# config.targets = [Target1.new, Target2.new]
|
86
|
+
# end
|
87
|
+
# Stenotype.config.targets #=> [target_obj1, target_obj2]
|
88
|
+
#
|
89
|
+
# @example When no targets have been configured
|
90
|
+
# Stenotype.configure { |config| config.targets = [] }
|
91
|
+
# Stenotype.config.targets #=> Stenotype::NoTargetsSpecifiedError
|
92
|
+
#
|
93
|
+
# @raise {Stenotype::NoTargetsSpecifiedError} in case no targets are configured
|
94
|
+
# @return {Array<#publish>} An array of targets implementing method [#publish]
|
95
|
+
#
|
96
|
+
def targets
|
97
|
+
return config.targets unless config.targets.empty?
|
98
|
+
|
99
|
+
raise Stenotype::NoTargetsSpecifiedError,
|
100
|
+
"Please configure a target(s) for events to be sent to. "\
|
101
|
+
"See #{Stenotype::Configuration} for reference."
|
102
|
+
end
|
48
103
|
end
|
49
104
|
end
|