eventboss 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c36cbbb5b46f114db4b05ca721ca4bbb54e0181c100c37a9897138f25b73ed4e
4
+ data.tar.gz: f720663f6c690177681bd7f22cd82cba6482778085335865cff901b1fc70ed12
5
+ SHA512:
6
+ metadata.gz: a3cedeaf4620288d2055c3af2349f7f532d2226063d66982e8bef3c85f26cfe9b4c1533baa05e30cb9380e1b901682b8d3f798441174dafbc3715e433701e40f
7
+ data.tar.gz: 01ce03e3a310998d5376741920bb2660306ecdf25f7daa0e3151f01dd14056f56bf2942954e51e5ff6e53e87ef6b8ad8adecc9140615ac431e0fb356dd07cdd3
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ eventboss (1.0.0)
5
+ aws-sdk-sns (>= 1.1.0)
6
+ aws-sdk-sqs (>= 1.3.0)
7
+ concurrent-ruby (~> 1.0, >= 1.0.5)
8
+ dotenv (~> 2.1, >= 2.1.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ aws-eventstream (1.0.3)
14
+ aws-partitions (1.161.0)
15
+ aws-sdk-core (3.51.0)
16
+ aws-eventstream (~> 1.0, >= 1.0.2)
17
+ aws-partitions (~> 1.0)
18
+ aws-sigv4 (~> 1.1)
19
+ jmespath (~> 1.0)
20
+ aws-sdk-sns (1.13.0)
21
+ aws-sdk-core (~> 3, >= 3.48.2)
22
+ aws-sigv4 (~> 1.1)
23
+ aws-sdk-sqs (1.13.0)
24
+ aws-sdk-core (~> 3, >= 3.48.2)
25
+ aws-sigv4 (~> 1.1)
26
+ aws-sigv4 (1.1.0)
27
+ aws-eventstream (~> 1.0, >= 1.0.2)
28
+ concurrent-ruby (1.1.5)
29
+ diff-lcs (1.3)
30
+ dotenv (2.7.2)
31
+ jmespath (1.4.0)
32
+ rake (12.3.1)
33
+ rspec (3.7.0)
34
+ rspec-core (~> 3.7.0)
35
+ rspec-expectations (~> 3.7.0)
36
+ rspec-mocks (~> 3.7.0)
37
+ rspec-core (3.7.0)
38
+ rspec-support (~> 3.7.0)
39
+ rspec-expectations (3.7.0)
40
+ diff-lcs (>= 1.2.0, < 2.0)
41
+ rspec-support (~> 3.7.0)
42
+ rspec-mocks (3.7.0)
43
+ diff-lcs (>= 1.2.0, < 2.0)
44
+ rspec-support (~> 3.7.0)
45
+ rspec-support (3.7.0)
46
+
47
+ PLATFORMS
48
+ ruby
49
+
50
+ DEPENDENCIES
51
+ bundler (~> 1.13)
52
+ eventboss!
53
+ rake (>= 10.0)
54
+ rspec (~> 3.0)
55
+
56
+ BUNDLED WITH
57
+ 1.17.2
data/Guardfile ADDED
@@ -0,0 +1,4 @@
1
+ guard 'rspec', cmd: 'bundle exec rspec --color' do
2
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
3
+ watch(%r|^spec/(.*)_spec\.rb|)
4
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 AirHelp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # Eventboss
2
+
3
+ Eventboss ruby client.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'eventboss'
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ Run the listener by:
16
+ ```
17
+ bundle exec eventboss
18
+ ```
19
+ it will read conf values from ENV variables in configuration sections.
20
+
21
+ ### Broadcasting events:
22
+
23
+ ```ruby
24
+ publisher = Eventboss.publisher(event_name)
25
+ publisher.publish(payload)
26
+ ```
27
+
28
+ ### Unicasting events in batches: (via SQS)
29
+
30
+ ```ruby
31
+ sender = Eventboss.sender(event_name, destination_app)
32
+ sender.send_batch([payload1, payload2])
33
+ ```
34
+
35
+ Receiving events via listeners:
36
+
37
+ ```ruby
38
+ class AnyName
39
+ include Eventboss::Listener
40
+ eventboss_options source_app: 'src_app_name', event_name: 'my_event'
41
+
42
+ def receive(payload)
43
+ end
44
+ end
45
+ ```
46
+
47
+
48
+ ## Configuration
49
+
50
+ By default, no exception will be raised when publisher configuration is missing (`eventboss_region`,
51
+ `eventboss_account_id`, `eventboss_app_name`). This can lead to false-positive specs, app not working without exceptions on dev/stg/prod environment. It's strongly advised to set `raise_on_missing_configuration` to true.
52
+
53
+ Using `.configure`:
54
+
55
+ ```ruby
56
+ Eventboss.configure do |config|
57
+ config.raise_on_missing_configuration = true
58
+ config.eventboss_account_id = 1234567
59
+ config.eventboss_app_name = name
60
+ config.eventboss_region = aws_region
61
+ config.concurrency = 10
62
+ # when using custom clients like localstack
63
+ config.sns_client = client # Custom SNS Client can be used, i.e. to use local mock, see: https://github.com/phstc/shoryuken/wiki/Using-a-local-mock-SQS-server
64
+ config.sqs_client = Aws::SQS::Client.new(endpoint: 'http://localstack:4576', region: 'us-east-1', credentials: Aws::Credentials.new('fake', 'fake'))
65
+ end
66
+ ```
67
+
68
+ Using ENVs:
69
+
70
+ ```
71
+ EVENTBUS_ACCOUNT_ID=12345676
72
+ EVENTBUS_APP_NAME=application_name
73
+ EVENTBUS_ENV=env_name # production/staging/test
74
+ EVENTBUS_REGION=aws_region # i.e. eu-west-1
75
+ EVENTBUS_CONCURRENCY=10 # default is 25
76
+
77
+ AWS_SNS_ENDPOINT=http://localhost:4575 # when using with localstack
78
+ AWS_SQS_ENDPOINT=http://localhost:4576 # when using with localstack
79
+ ```
80
+
81
+ ### Logging and error handling
82
+ To have more verbose logging, set `log_level` in configuration (default is `info`).
83
+
84
+ Logger is used as default error handler. There is Airbrake handler available, to use it ensure you have `airbrake` or `airbrake-ruby` gem and add it to error handlers stack:
85
+
86
+ ```ruby
87
+ Eventboss.configure do |config|
88
+ config.error_handlers << Eventboss::ErrorHandlers::Airbrake.new
89
+ end
90
+ ```
91
+
92
+ ### Polling strategy
93
+
94
+ Default is `Eventboss::Polling::Basic`. See `eventboss/polling/*` for other options. The configuration should be a `lambda` like so:
95
+
96
+ ```ruby
97
+ Eventboss.configure do |config|
98
+ config.polling_strategy = lambda { |queues| Eventboss::Polling::TimedRoundRobin.new(queues) }
99
+ end
100
+ ```
101
+
102
+ ## Topics & Queues naming convention
103
+
104
+ The SNSes should be name in the following pattern:
105
+ ```
106
+ eventboss-{src_app_name}-{event_name}-{environment}
107
+ ```
108
+
109
+ i.e.
110
+ ```
111
+ eventboss-srcapp-transaction_change-staging
112
+ ```
113
+
114
+ The corresponding SQSes should be name like:
115
+ ```
116
+ {dest_app_name}-eventboss-{src_app_name}-{event_name}-{environment}
117
+ {dest_app_name}-eventboss-{src_app_name}-{event_name}-{environment}-deadletter
118
+ ```
119
+ i.e.
120
+ ```
121
+ destapp-eventboss-srcapp-transaction_change-staging
122
+ destapp-eventboss-srcapp-transaction_change-staging-deadletter
123
+ ```
124
+
125
+ ## Contributing
126
+
127
+ Bug reports and pull requests are welcome on GitHub at https://github.com/AirHelp/eventboss.
128
+
129
+
130
+ ## License
131
+
132
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/eventboss ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'dotenv'
5
+ require 'eventboss'
6
+ require 'optparse'
7
+
8
+ Dotenv.load
9
+
10
+ STDOUT.sync = true
11
+ options = {}
12
+
13
+ OptionParser.new do |parser|
14
+ parser.on('-r', '--require LIBRARY', 'Require custom app entrypoint') do |lib|
15
+ options[:require] = lib
16
+ end
17
+ end.parse!
18
+
19
+ begin
20
+ logger = Eventboss::Logger
21
+
22
+ require 'rails'
23
+ logger.debug('Loading rails...')
24
+ if ::Rails::VERSION::MAJOR < 4
25
+ require File.expand_path('config/environment.rb')
26
+ else
27
+ require File.expand_path('config/application.rb')
28
+ require File.expand_path('config/environment.rb')
29
+ end
30
+ ::Rails.application.eager_load!
31
+ rescue LoadError
32
+ logger.debug('Seems like not a Rails app')
33
+
34
+ if options[:require].nil?
35
+ logger.warn('Please use -r to load a custom app entrypoint')
36
+ exit(0)
37
+ else
38
+ logger.debug("Loading #{options[:require]}")
39
+ require File.expand_path(options[:require])
40
+ end
41
+ end
42
+
43
+ logger.info('Starting eventboss...')
44
+ logger.info('Active Listeners:')
45
+ logger.info(Eventboss::QueueListener.list.to_s)
46
+
47
+ Eventboss.launch
data/eventboss.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'eventboss/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "eventboss"
8
+ spec.version = Eventboss::VERSION
9
+ spec.authors = ["AirHelp"]
10
+ spec.email = ["marcin.naglik@airhelp.com"]
11
+
12
+ spec.summary = %q{Eventboss Ruby Client.}
13
+ spec.description = %q{Eventboss Ruby Client.}
14
+ spec.homepage = "https://airhelp.com"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.executables = ["eventboss"]
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.5"
24
+ spec.add_dependency "aws-sdk-sqs", ">= 1.3.0"
25
+ spec.add_dependency "aws-sdk-sns", ">= 1.1.0"
26
+ spec.add_dependency "dotenv", "~> 2.1", ">= 2.1.1"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.13"
29
+ spec.add_development_dependency 'rake', '>= 10.0'
30
+ spec.add_development_dependency "rspec", "~> 3.0"
31
+ end
data/lib/eventboss.rb ADDED
@@ -0,0 +1,79 @@
1
+ require 'aws-sdk-sqs'
2
+ require 'aws-sdk-sns'
3
+ require 'concurrent'
4
+ require 'securerandom'
5
+
6
+ require 'eventboss/version'
7
+ require 'eventboss/configuration'
8
+ require 'eventboss/instrumentation'
9
+ require 'eventboss/sns_client'
10
+ require 'eventboss/queue'
11
+ require 'eventboss/queue_listener'
12
+ require 'eventboss/listener'
13
+ require 'eventboss/logging'
14
+ require 'eventboss/safe_thread'
15
+ require 'eventboss/launcher'
16
+ require 'eventboss/long_poller'
17
+ require 'eventboss/unit_of_work'
18
+ require 'eventboss/worker'
19
+ require 'eventboss/fetcher'
20
+ require 'eventboss/publisher'
21
+ require 'eventboss/sender'
22
+ require 'eventboss/manager'
23
+ require 'eventboss/runner'
24
+ require 'eventboss/logger'
25
+ require 'eventboss/polling/basic'
26
+ require 'eventboss/polling/timed_round_robin'
27
+ require 'eventboss/extensions'
28
+
29
+ # For Rails use railtie, for plain Ruby apps use custom scripts loader
30
+ if defined?(Rails)
31
+ require 'eventboss/railtie'
32
+ else
33
+ require 'eventboss/scripts'
34
+ end
35
+
36
+ module Eventboss
37
+ Shutdown = Class.new(StandardError)
38
+
39
+ class << self
40
+ def publisher(event_name, opts = {})
41
+ Publisher.new(event_name, configuration.sns_client, configuration, opts)
42
+ end
43
+
44
+ def sender(event_name, destination_app, options = {})
45
+ queue_name = Queue.build_name(
46
+ destination: destination_app,
47
+ source: configuration.eventboss_app_name,
48
+ event: event_name,
49
+ env: env,
50
+ generic: options[:generic]
51
+ )
52
+
53
+ Sender.new(
54
+ client: configuration.sqs_client,
55
+ queue: Queue.new(queue_name)
56
+ )
57
+ end
58
+
59
+ def listen
60
+ Eventboss::Runner.start
61
+ end
62
+
63
+ def launch
64
+ Eventboss::Runner.launch
65
+ end
66
+
67
+ def env
68
+ @env ||= ENV['EVENTBUS_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV']
69
+ end
70
+
71
+ def configure
72
+ yield configuration if block_given?
73
+ end
74
+
75
+ def configuration
76
+ @_configuration ||= Configuration.new
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,104 @@
1
+ module Eventboss
2
+ class Configuration
3
+ attr_writer :raise_on_missing_configuration,
4
+ :error_handlers,
5
+ :concurrency,
6
+ :log_level,
7
+ :sns_client,
8
+ :sqs_client,
9
+ :eventboss_region,
10
+ :eventboss_app_name,
11
+ :eventboss_account_id,
12
+ :aws_access_key_id,
13
+ :aws_secret_access_key,
14
+ :polling_strategy,
15
+ :aws_sns_endpoint,
16
+ :aws_sqs_endpoint,
17
+ :sns_sqs_name_infix
18
+
19
+ def raise_on_missing_configuration
20
+ defined_or_default('raise_on_missing_configuration') { false }
21
+ end
22
+
23
+ def error_handlers
24
+ defined_or_default('error_handlers') { [ErrorHandlers::Logger.new] }
25
+ end
26
+
27
+ def concurrency
28
+ defined_or_default('concurrency') { ENV['EVENTBUS_CONCURRENCY'] ? ENV['EVENTBUS_CONCURRENCY'].to_i : 25 }
29
+ end
30
+
31
+ def log_level
32
+ defined_or_default('log_level') { :info }
33
+ end
34
+
35
+ def sns_client
36
+ defined_or_default('sns_client') { Eventboss::SnsClient.new(self) }
37
+ end
38
+
39
+ def sqs_client
40
+ defined_or_default('sqs_client') do
41
+ options = {
42
+ region: eventboss_region,
43
+ credentials: Aws::Credentials.new(
44
+ aws_access_key_id,
45
+ aws_secret_access_key
46
+ )
47
+ }
48
+ if aws_sqs_endpoint
49
+ options[:endpoint] = aws_sqs_endpoint
50
+ end
51
+
52
+ Aws::SQS::Client.new(options)
53
+ end
54
+ end
55
+
56
+ def eventboss_region
57
+ defined_or_default('eventboss_region') { ENV['EVENTBUS_REGION'] }
58
+ end
59
+
60
+ def eventboss_app_name
61
+ defined_or_default('eventboss_app_name') { ENV['EVENTBUS_APP_NAME'] }
62
+ end
63
+
64
+ def eventboss_account_id
65
+ defined_or_default('eventboss_account_id') { ENV['EVENTBUS_ACCOUNT_ID'] }
66
+ end
67
+
68
+ def aws_access_key_id
69
+ defined_or_default('aws_access_key_id') { ENV['AWS_ACCESS_KEY_ID'] }
70
+ end
71
+
72
+ def aws_secret_access_key
73
+ defined_or_default('aws_secret_access_key') { ENV['AWS_SECRET_ACCESS_KEY'] }
74
+ end
75
+
76
+ def aws_sqs_endpoint
77
+ defined_or_default('aws_sqs_endpoint') { ENV['AWS_SQS_ENDPOINT'] }
78
+ end
79
+
80
+ def aws_sns_endpoint
81
+ defined_or_default('aws_sns_endpoint') { ENV['AWS_SNS_ENDPOINT'] }
82
+ end
83
+
84
+ def polling_strategy
85
+ defined_or_default('polling_strategy') do
86
+ lambda { |queues| Eventboss::Polling::Basic.new(queues) }
87
+ end
88
+ end
89
+
90
+ def sns_sqs_name_infix
91
+ defined_or_default('sns_sqs_name_infix') { ENV['EVENTBUS_SQS_SNS_NAME_INFIX'] || '-eventboss-' }
92
+ end
93
+
94
+ private
95
+
96
+ def defined_or_default(variable_name)
97
+ if instance_variable_defined?("@#{variable_name}")
98
+ instance_variable_get("@#{variable_name}")
99
+ else
100
+ instance_variable_set("@#{variable_name}", yield) if block_given?
101
+ end
102
+ end
103
+ end
104
+ end