stenotype 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +7 -0
- data/.yardopts +2 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +239 -0
- data/LICENSE.txt +21 -0
- data/README.md +251 -0
- data/Rakefile +8 -0
- data/TODO.md +17 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/stenotype/adapters/base.rb +36 -0
- data/lib/stenotype/adapters/google_cloud.rb +56 -0
- data/lib/stenotype/adapters/stdout_adapter.rb +23 -0
- data/lib/stenotype/adapters.rb +5 -0
- data/lib/stenotype/configuration.rb +49 -0
- data/lib/stenotype/context_handlers/base.rb +52 -0
- data/lib/stenotype/context_handlers/collection.rb +64 -0
- data/lib/stenotype/context_handlers/klass.rb +20 -0
- data/lib/stenotype/context_handlers/rails/active_job.rb +43 -0
- data/lib/stenotype/context_handlers/rails/controller.rb +34 -0
- data/lib/stenotype/context_handlers.rb +32 -0
- data/lib/stenotype/dispatcher.rb +37 -0
- data/lib/stenotype/event.rb +59 -0
- data/lib/stenotype/event_serializer.rb +61 -0
- data/lib/stenotype/exceptions.rb +31 -0
- data/lib/stenotype/frameworks/object_ext.rb +145 -0
- data/lib/stenotype/frameworks/rails/action_controller.rb +110 -0
- data/lib/stenotype/frameworks/rails/active_job.rb +57 -0
- data/lib/stenotype/version.rb +7 -0
- data/lib/stenotype.rb +98 -0
- data/stenotype.gemspec +47 -0
- metadata +262 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'google/cloud/pubsub'
|
4
|
+
|
5
|
+
module Stenotype
|
6
|
+
module Adapters
|
7
|
+
#
|
8
|
+
# An adapter implementing method {#publish} to send data to Google Cloud PubSub
|
9
|
+
#
|
10
|
+
class GoogleCloud < Base
|
11
|
+
#
|
12
|
+
# @param event_data {Hash} The data to be published to Google Cloud
|
13
|
+
# @raise {Stenotype::Exceptions::GoogleCloudUnsupportedMode} unless the mode
|
14
|
+
# in configured to be :sync or :async
|
15
|
+
# @raise {Stenotype::Exceptions::MessageNotPublished} unless message is published
|
16
|
+
#
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
18
|
+
#
|
19
|
+
def publish(event_data, **additional_arguments)
|
20
|
+
case config.gc_mode
|
21
|
+
when :async
|
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)
|
27
|
+
else
|
28
|
+
raise Stenotype::Exceptions::GoogleCloudUnsupportedMode,
|
29
|
+
'Please use either :sync or :async modes for publishing the events.'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
# rubocop:enable Metrics/MethodLength
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# :nocov:
|
37
|
+
def client
|
38
|
+
@client ||= Google::Cloud::PubSub.new(
|
39
|
+
project_id: config.gc_project_id,
|
40
|
+
credentials: config.gc_credentials
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Use memoization, otherwise a new topic will be created
|
45
|
+
# every time. And a new async_publisher will be created.
|
46
|
+
# :nocov:
|
47
|
+
def topic
|
48
|
+
@topic ||= client.topic config.gc_topic
|
49
|
+
end
|
50
|
+
|
51
|
+
def config
|
52
|
+
Stenotype.config
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
module Adapters
|
5
|
+
#
|
6
|
+
# An adapter implementing method {#publish} to send data to STDOUT
|
7
|
+
#
|
8
|
+
class StdoutAdapter < Base
|
9
|
+
#
|
10
|
+
# @param event_data {Hash} The data to be published to STDOUT
|
11
|
+
#
|
12
|
+
def publish(event_data, **additional_arguments)
|
13
|
+
client.info(event_data, **additional_arguments)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def client
|
19
|
+
@client ||= Logger.new(STDOUT)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
#
|
5
|
+
# A module containing freshly-event gem configuration
|
6
|
+
#
|
7
|
+
module Configuration
|
8
|
+
class << self
|
9
|
+
# @return {Array<#publish>} a list of targets responding to method [#publish]
|
10
|
+
attr_writer :targets
|
11
|
+
# @return {Sting} a string with GC API credential. Refer to GC PubSub documentation
|
12
|
+
attr_accessor :gc_credentials
|
13
|
+
# @return {String} a name of the project in GC PubSub
|
14
|
+
attr_accessor :gc_project_id
|
15
|
+
# @return {String} a name of the topic in GC PubSub
|
16
|
+
attr_accessor :gc_topic
|
17
|
+
# @return [:sync, :async] GC publish mode
|
18
|
+
attr_accessor :gc_mode
|
19
|
+
# @return {#publish} as object responding to method [#publish]
|
20
|
+
attr_accessor :dispatcher
|
21
|
+
# @return {#uuid} an object responding to method [#uuid]
|
22
|
+
attr_accessor :uuid_generator
|
23
|
+
|
24
|
+
#
|
25
|
+
# Yields control to the caller
|
26
|
+
# @yield {Stenotype::Configuration}
|
27
|
+
# @return {Stenotype::Configuration}
|
28
|
+
#
|
29
|
+
def configure
|
30
|
+
yield self
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# @raise {Stenotype::Exceptions::NoTargetsSpecified} in case no targets are configured
|
36
|
+
# @return {Array<#publish>} An array of targets implementing method [#publish]
|
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
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
module ContextHandlers
|
5
|
+
#
|
6
|
+
# An abstract base class for implementing contexts handlers
|
7
|
+
#
|
8
|
+
# @abstract
|
9
|
+
# @attr_reader {Object} context A context in which the event was emitted
|
10
|
+
# @attr_reader {Hash} options A hash of additional options
|
11
|
+
#
|
12
|
+
class Base
|
13
|
+
attr_reader :context, :options
|
14
|
+
|
15
|
+
#
|
16
|
+
# @param context {Object} A context where the event was emitted
|
17
|
+
# @param options {Hash} A hash of additional options
|
18
|
+
#
|
19
|
+
# @return {#as_json} A context handler implementing [#as_json]
|
20
|
+
#
|
21
|
+
def initialize(context, options = {})
|
22
|
+
@context = context
|
23
|
+
@options = options
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# @abstract
|
28
|
+
# @raise {NotImplementedError} subclasses must implement this method
|
29
|
+
#
|
30
|
+
def as_json(*_args)
|
31
|
+
raise NotImplementedError, "#{self} must implement method ##{__method__}"
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# @attr_writer {Symbol} handler_name The name under which a handler is going to be registered
|
36
|
+
#
|
37
|
+
class << self
|
38
|
+
# Handler name by which it will be registered in {Stenotype::ContextHandlers::Collection}
|
39
|
+
attr_writer :handler_name
|
40
|
+
|
41
|
+
#
|
42
|
+
# @return {Symbol} Name of the handler
|
43
|
+
# @raise {NotImplementedError} in case handler name is not specified.
|
44
|
+
#
|
45
|
+
def handler_name
|
46
|
+
@handler_name || raise(NotImplementedError,
|
47
|
+
"Please, specify the handler_name of #{self}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
module ContextHandlers
|
5
|
+
#
|
6
|
+
# A class representing a list of available context handlers
|
7
|
+
#
|
8
|
+
class Collection < Array
|
9
|
+
#
|
10
|
+
# @param handler_name {Symbol} a handler to be found in the collection
|
11
|
+
# @raise {Stenotype::Exceptions::UnknownHandler} in case a handler is not registered
|
12
|
+
# @return {#as_json} A handler which respond to #as_json
|
13
|
+
#
|
14
|
+
def choose(handler_name:)
|
15
|
+
handler = detect { |e| e.handler_name == handler_name }
|
16
|
+
handler || raise(Stenotype::Exceptions::UnknownHandler,
|
17
|
+
"Handler '#{handler_name}' is not found. " \
|
18
|
+
"Please make sure the handler you've specified is " \
|
19
|
+
'registered in the list of known handlers. ' \
|
20
|
+
"See #{Stenotype::ContextHandlers} for more information.")
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# @param handler {#as_json} a new handler to be added to collection
|
25
|
+
# @raise {ArgumentError} in case handler does not inherit from {Stenotype::ContextHandlers::Base}
|
26
|
+
# @return {Stenotype::ContextHandlers::Collection} a collection object
|
27
|
+
#
|
28
|
+
def register(handler)
|
29
|
+
unless handler < Stenotype::ContextHandlers::Base
|
30
|
+
raise ArgumentError,
|
31
|
+
"Handler must inherit from #{Stenotype::ContextHandlers::Base}, " \
|
32
|
+
"but inherited from #{handler.superclass}"
|
33
|
+
end
|
34
|
+
|
35
|
+
push(handler) unless registered?(handler)
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# @param handler {#as_json} a handler to be removed from the collection of known handlers
|
41
|
+
# @raise {ArgumentError} in case handler does not inherit from {Stenotype::ContextHandlers::Base}
|
42
|
+
# @return {Stenotype::ContextHandlers::Collection} a collection object
|
43
|
+
#
|
44
|
+
def unregister(handler)
|
45
|
+
unless handler < Stenotype::ContextHandlers::Base
|
46
|
+
raise ArgumentError,
|
47
|
+
"Handler must inherit from #{Stenotype::ContextHandlers::Base}, " \
|
48
|
+
"but inherited from #{handler.superclass}"
|
49
|
+
end
|
50
|
+
|
51
|
+
delete(handler) if registered?(handler)
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# @param handler {#as_json} a handler to be checked for presence in a collection
|
57
|
+
# @return [true, false]
|
58
|
+
#
|
59
|
+
def registered?(handler)
|
60
|
+
include?(handler)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
module ContextHandlers
|
5
|
+
#
|
6
|
+
# Plain Ruby class handler to support fetching data from a class
|
7
|
+
#
|
8
|
+
class Klass < Stenotype::ContextHandlers::Base
|
9
|
+
self.handler_name = :klass
|
10
|
+
|
11
|
+
#
|
12
|
+
# @todo r.kapitonov Figure out the params
|
13
|
+
# @return {Hash} a JSON representation of a Ruby class
|
14
|
+
#
|
15
|
+
def as_json(*_args)
|
16
|
+
{}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
module ContextHandlers
|
5
|
+
#
|
6
|
+
# A namespace containing extension of rails components
|
7
|
+
# for fetching specific data from those components.
|
8
|
+
# For example fetching request from a controller context,
|
9
|
+
# or fetching ActiveJob attributes from an ActiveJob instance
|
10
|
+
#
|
11
|
+
module Rails
|
12
|
+
#
|
13
|
+
# ActiveJob handler to support fetching data out of an ActiveJob instance
|
14
|
+
#
|
15
|
+
class ActiveJob < Stenotype::ContextHandlers::Base
|
16
|
+
self.handler_name = :active_job
|
17
|
+
|
18
|
+
#
|
19
|
+
# @todo How to deal with _args? It won't necessarily respond to #as_json
|
20
|
+
# @return {Hash} a JSON representation of job's data
|
21
|
+
#
|
22
|
+
def as_json(*_args)
|
23
|
+
{
|
24
|
+
job_id: job_id,
|
25
|
+
enqueued_at: Time.now,
|
26
|
+
queue_name: queue_name,
|
27
|
+
class: context.class.name
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def job_id
|
34
|
+
context.job_id
|
35
|
+
end
|
36
|
+
|
37
|
+
def queue_name
|
38
|
+
context.queue_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
module ContextHandlers
|
5
|
+
module Rails
|
6
|
+
#
|
7
|
+
# ActionController handler to support fetching data out of a rails controller instance
|
8
|
+
#
|
9
|
+
class Controller < Stenotype::ContextHandlers::Base
|
10
|
+
self.handler_name = :controller
|
11
|
+
|
12
|
+
#
|
13
|
+
# @return {Hash} a JSON representation of controller's data
|
14
|
+
#
|
15
|
+
def as_json(*_args)
|
16
|
+
{
|
17
|
+
class: request.controller_class.name,
|
18
|
+
method: request.method,
|
19
|
+
url: request.url,
|
20
|
+
referer: request.referer,
|
21
|
+
params: request.params.except('controller', 'action'),
|
22
|
+
ip: request.remote_ip
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def request
|
29
|
+
context.request
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stenotype/context_handlers/base'
|
4
|
+
require 'stenotype/context_handlers/rails/controller'
|
5
|
+
require 'stenotype/context_handlers/rails/active_job'
|
6
|
+
require 'stenotype/context_handlers/klass'
|
7
|
+
require 'stenotype/context_handlers/collection'
|
8
|
+
|
9
|
+
module Stenotype
|
10
|
+
#
|
11
|
+
# A namespace to contain various context
|
12
|
+
# handlers implementations
|
13
|
+
#
|
14
|
+
module ContextHandlers
|
15
|
+
class << self
|
16
|
+
attr_writer :known
|
17
|
+
#
|
18
|
+
# @return {Array<#publish>} A list of handlers implementing [#publish]
|
19
|
+
#
|
20
|
+
def known
|
21
|
+
@known ||= Stenotype::ContextHandlers::Collection.new
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# @param handler {#publish} A handler with implemented method [#publish]
|
26
|
+
#
|
27
|
+
def register(handler)
|
28
|
+
known.register(handler)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
#
|
5
|
+
# {Stenotype::Dispatcher} is responsible for gluing together
|
6
|
+
# publishing targets and data gathering.
|
7
|
+
#
|
8
|
+
class Dispatcher
|
9
|
+
#
|
10
|
+
# Publishes an event to the list of configured targets.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# event = Stenotype::Event.new(data, options, eval_context)
|
15
|
+
# Stenotype::Dispatcher.new.publish(event)
|
16
|
+
#
|
17
|
+
# @param event {Stenotype::Event} An instance of event to be published.
|
18
|
+
# @param serializer {#serialize} A class responsible for serializing the event
|
19
|
+
# @return {Stenotype::Dispatcher} for the sake of chaining
|
20
|
+
#
|
21
|
+
def publish(event, serializer: Stenotype::EventSerializer)
|
22
|
+
event_data = serializer.new(event).serialize
|
23
|
+
|
24
|
+
targets.each do |t|
|
25
|
+
t.publish(event_data)
|
26
|
+
end
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def targets
|
34
|
+
Stenotype.config.targets
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
#
|
5
|
+
# {Stenotype::Event} represents a triggered event
|
6
|
+
#
|
7
|
+
class Event
|
8
|
+
#
|
9
|
+
# Delegates event to instance of {Stenotype::Event}.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# Stenotype::Event.emit!(data, options, eval_context)
|
14
|
+
#
|
15
|
+
# @param data {Hash} Data to be published to the targets.
|
16
|
+
# @param options {Hash} A hash of additional options to be tracked.
|
17
|
+
# @param eval_context {Hash} A context having handler defined in {Stenotype::ContextHandlers}.
|
18
|
+
# @param dispatcher {#publish} A dispatcher object responding to [#publish]
|
19
|
+
# @return {Stenotype::Event} An instance of {Stenotype::Event}
|
20
|
+
#
|
21
|
+
def self.emit!(data, options: {}, eval_context: {}, dispatcher: Stenotype.config.dispatcher)
|
22
|
+
event = new(data, options: options, eval_context: eval_context, dispatcher: dispatcher)
|
23
|
+
event.emit!
|
24
|
+
event
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :data, :options, :eval_context, :dispatcher
|
28
|
+
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
#
|
32
|
+
# Stenotype::Event.emit!(data, options, eval_context)
|
33
|
+
#
|
34
|
+
# @param {Hash} data Data to be published to the targets.
|
35
|
+
# @param {Hash} options A hash of additional options to be tracked.
|
36
|
+
# @param {Hash} eval_context A context having handler defined in {Stenotype::ContextHandlers}.
|
37
|
+
# @param dispatcher {#publish} A dispatcher object responding to [#publish].
|
38
|
+
# @return {Stenotype::Event} An instance of event
|
39
|
+
#
|
40
|
+
def initialize(data, options: {}, eval_context: {}, dispatcher: Stenotype.config.dispatcher)
|
41
|
+
@data = data
|
42
|
+
@options = options
|
43
|
+
@eval_context = eval_context
|
44
|
+
@dispatcher = dispatcher
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Emits a {Stenotype::Event}.
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
#
|
52
|
+
# event = Stenotype::Event.new(data, options, eval_context)
|
53
|
+
# event.emit!
|
54
|
+
#
|
55
|
+
def emit!
|
56
|
+
dispatcher.publish(self)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module Stenotype
|
5
|
+
#
|
6
|
+
# A class used to serialize a {Stenotype::Event}
|
7
|
+
# upon publishing it to targets
|
8
|
+
#
|
9
|
+
class EventSerializer
|
10
|
+
attr_reader :event, :uuid_generator
|
11
|
+
|
12
|
+
#
|
13
|
+
# @param event {Stenotype::Event}
|
14
|
+
# @param uuid_generator {#uuid} an object responding to [#uuid]
|
15
|
+
#
|
16
|
+
def initialize(event, uuid_generator: Stenotype.config.uuid_generator)
|
17
|
+
@event = event
|
18
|
+
@uuid_generator = uuid_generator
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# @return {Hash} A hash representation of the event and its context
|
23
|
+
#
|
24
|
+
def serialize
|
25
|
+
{
|
26
|
+
**event_data,
|
27
|
+
**event_options,
|
28
|
+
**default_options,
|
29
|
+
**eval_context_options
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def event_data
|
36
|
+
event.data
|
37
|
+
end
|
38
|
+
|
39
|
+
def event_options
|
40
|
+
event.options
|
41
|
+
end
|
42
|
+
|
43
|
+
def eval_context
|
44
|
+
event.eval_context
|
45
|
+
end
|
46
|
+
|
47
|
+
def eval_context_options
|
48
|
+
eval_context.map do |context_name, context|
|
49
|
+
handler = Stenotype::ContextHandlers.known.choose(handler_name: context_name)
|
50
|
+
handler.new(context).as_json
|
51
|
+
end.reduce(:merge!) || {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_options
|
55
|
+
{
|
56
|
+
timestamp: Time.now.utc,
|
57
|
+
uuid: uuid_generator.uuid
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
#
|
5
|
+
# A namespace for holding library-level exceptions.
|
6
|
+
#
|
7
|
+
module Exceptions
|
8
|
+
#
|
9
|
+
# This exception is being raised in case an unsupported mode
|
10
|
+
# for Google Cloud is specified.
|
11
|
+
#
|
12
|
+
class GoogleCloudUnsupportedMode < StandardError; end
|
13
|
+
|
14
|
+
#
|
15
|
+
# This exception is being raised upon unsuccessful publishing of an event.
|
16
|
+
#
|
17
|
+
class MessageNotPublished < StandardError; end
|
18
|
+
|
19
|
+
#
|
20
|
+
# This exception is being raised in case no targets are
|
21
|
+
# specified {Stenotype::Configuration}.
|
22
|
+
#
|
23
|
+
class NoTargetsSpecified < StandardError; end
|
24
|
+
|
25
|
+
#
|
26
|
+
# This exception is being raised upon using a context handler which
|
27
|
+
# has never been registered in known handlers in {Stenotype::ContextHandlers::Collection}.
|
28
|
+
#
|
29
|
+
class UnknownHandler < StandardError; end
|
30
|
+
end
|
31
|
+
end
|