eventosaurus 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
+ SHA1:
3
+ metadata.gz: 1a8ef4f20b8d48c0c0e035f514ba4088578e9068
4
+ data.tar.gz: 9038157130f2b42586d4fee746a3ebd394d3d0c2
5
+ SHA512:
6
+ metadata.gz: 90643659fb8232e9f6d713d946adbd8f984d49038d00a9095bd30a79df287796603ffcb449104ea79829f8f4944dd0906d5a204742d72a66579739d8888116a9
7
+ data.tar.gz: 158959e5a2f144a853cf7fa300301dde2d08dc742143b98ab826984ee081d79981d9a40a73df7bce2b38d28602e10e94cfcfd076fc6000c504c1bc171b50cb02
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /*.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,28 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+ Include:
4
+ - ./Rakefile
5
+ Exclude:
6
+ - bin/**/*
7
+ - vendor/bundle/**/*
8
+
9
+ Lint/EndAlignment:
10
+ AlignWith: variable
11
+
12
+ Metrics/LineLength:
13
+ Max: 120
14
+
15
+ Style/AlignParameters:
16
+ Enabled: false
17
+
18
+ Style/Documentation:
19
+ Enabled: false
20
+
21
+ Style/DotPosition:
22
+ EnforcedStyle: leading
23
+
24
+ Style/FrozenStringLiteralComment:
25
+ Enabled: false
26
+
27
+ Style/StringLiterals:
28
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,46 @@
1
+ # 1.0.0
2
+
3
+ * changes name to 'eventosaurus'
4
+ * adds a test_mode
5
+
6
+ # 0.6.0
7
+
8
+ * uses event_uuid as sort key rather than created_at
9
+
10
+ # 0.5.5
11
+
12
+ * fixes bug in chainable local secondary indices
13
+
14
+ # 0.5.4
15
+
16
+ * set default sidekiq retry count to 3
17
+ * fix logger bug
18
+
19
+ # 0.5.3
20
+
21
+ * scope rake tasks to environment_prefix
22
+
23
+ # 0.5.2
24
+
25
+ * first release after code review
26
+
27
+ # 0.5.1
28
+
29
+ # 0.5.0
30
+
31
+ * adds dynamic query methods based on table definition
32
+
33
+ # 0.4.0
34
+
35
+ * removes dynamoid gem in favor of native aws-sdk usage
36
+ * adds rake tasks to build tables
37
+
38
+ # 0.3.0
39
+
40
+ * use Sidekiq for delayed jobs
41
+ * utilize Configuration class
42
+ * event jobs are idempotent
43
+
44
+ # 0.2.0
45
+
46
+ * uses DynamoID 1.1.0
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at engineering@blueapron.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in eventosaurus.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Blue Apron, inc.
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,307 @@
1
+ # Eventosaurus
2
+
3
+ [![CircleCI](https://circleci.com/gh/blueapron/eventosaurus.svg?style=shield)](https://circleci.com/gh/blueapron/eventosaurus)
4
+ [![Code Climate](https://codeclimate.com/github/blueapron/eventosaurus/badges/gpa.svg)](https://codeclimate.com/github/blueapron/eventosaurus)
5
+ [![Test Coverage](https://codeclimate.com/github/blueapron/eventosaurus/badges/coverage.svg)](https://codeclimate.com/github/blueapron/eventosaurus/coverage)
6
+ [![Issue Count](https://codeclimate.com/github/blueapron/eventosaurus/badges/issue_count.svg)](https://codeclimate.com/github/blueapron/eventosaurus)
7
+ [![Dependency Status](https://gemnasium.com/badges/github.com/blueapron/eventosaurus.svg)](https://gemnasium.com/github.com/blueapron/eventosaurus)
8
+
9
+ Enables easy asynchronous event storing and querying on [DynamoDB][dynamodb]
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'eventosaurus'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install eventosaurus
26
+
27
+
28
+ ## Setting up a local DynamoDB server
29
+
30
+ When developing, use the local DynamoDB server. Install and kick off your local instance:
31
+
32
+ Set the following environment variables:
33
+
34
+ ```
35
+ EVENT_ENVIRONMENT_PREFIX=localhost
36
+ AWS_ENDPOINT=http://localhost:8000
37
+ ```
38
+
39
+ Install and kick off DynamoDB:
40
+
41
+ ```bash
42
+ $ brew install dynamodb-local
43
+ $ ln -sfv /usr/local/opt/dynamodb-local/*.plist ~/Library/LaunchAgents
44
+ $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.dynamodb-local.plist
45
+ ```
46
+
47
+ ## Configuration
48
+
49
+ You need to add the following initializer (ex: `config/initializers/eventosaurus.rb`):
50
+
51
+ ```ruby
52
+ Eventosaurus.configure do |config|
53
+ config.use_sidekiq
54
+
55
+ # ex: localhost, productions
56
+ config.environment_prefix = ENV['EVENT_ENVIRONMENT_PREFIX']
57
+
58
+ config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
59
+ config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
60
+ config.aws_region = ENV['AWS_REGION']
61
+
62
+ # optional, used for local dynamodb
63
+ config.aws_endpoint = ENV['AWS_ENDPOINT']
64
+ end
65
+ ```
66
+
67
+ ### Sidekiq Alternatives
68
+
69
+ Eventosaurus ships with both synchronous and asynchronous options. By default Eventosaurus uses sidekiq to persist data to DynamoDB asynchronously.
70
+
71
+ For synchronous persistance:
72
+ ```ruby
73
+ Eventosaurus.configure do |config|
74
+ # ...
75
+ config.use_synchronous
76
+ # ...
77
+ end
78
+ ```
79
+
80
+ To use your own persistence mechanism, reference the below two files:
81
+
82
+ * [`lib/eventosaurus/persistors/sidekiq.rb`](https://github.com/blueapron/eventosaurus/blob/master/lib/eventosaurus/persistors/sidekiq.rb)
83
+ * [`lib/eventosaurus/workers/sidekiq.rb`](https://github.com/blueapron/eventosaurus/blob/master/lib/eventosaurus/workers/sidekiq.rb)
84
+
85
+ And include it in your configuration
86
+
87
+ ```ruby
88
+ require 'custom_persistor'
89
+ Eventosaurus.configure do |config|
90
+ # ...
91
+ config.persistor = CustomPersistor
92
+ # ...
93
+ end
94
+ ```
95
+
96
+ ## Event Representation
97
+
98
+ Every event type is represented by a class that includes `Eventosaurus::Storable`. Each class must do two things:
99
+
100
+ 0. define the table using the `table_definition` macro
101
+ 1. define the `details` class method, which defines the event interface
102
+
103
+ Here is an example of an event definition:
104
+
105
+ ```ruby
106
+ module Events
107
+ class PhoneCall
108
+ include Eventosaurus::Storable
109
+
110
+ table_definition name: :phone_call, partition_key: { person_id: :n }
111
+
112
+ def self.details( person_id:, phone_number:, last_called:)
113
+ {
114
+ 'person_id' => person_id
115
+ 'phone_number' => phone_number.to_s,
116
+ 'last_called' => last_called
117
+ }
118
+ end
119
+ end
120
+ end
121
+ ```
122
+
123
+ There are some built-in attributes for your events:
124
+
125
+ 0. the gem defines the range of your partition key to be `event_uuid.` When writing an event, this attribute is enforced to be unique, preventing duplicate writes. See Event Duplication Prevention below.
126
+ 0. the event also stores the timestamp, which represents the time when the gem client calls `.store`
127
+
128
+ ## Building the Tables
129
+
130
+ DynamoDB must have the tables needed to run your events. Once you've written your event classes you must run a rake task to create the tables. The tables are namespaced by your environment, as defined in the environment_prefix variable mentioned above. So if you build locally, the table name might be `localhost_core_customer_audit`. This will allow us to quickly get up and running on new environments. For the time being, the rake task expects your event definitions to be in `app/models/events`. **Be sure to put them there!**. Rake tasks are scoped to only work with tables that begin with your environment_prefix. This means even if staging and production point to the same dynamodb account, the `drop_tables` task will only drop tables from the environment specified.
131
+
132
+ ```
133
+ rake eventosaurus:create_tables
134
+ ```
135
+ *(NOTE: in the short term, you will have to manually run this create tables task upon deploy, as well as staging environments and anyone who pulls code utilizing these tables. This is temporary and there is an [outstanding task](https://app.asana.com/0/35948616193167/101210257934375) to change this.)*
136
+
137
+
138
+ You may then verify the tables were created:
139
+
140
+ ```
141
+ rake eventosaurus:list_tables
142
+ ```
143
+
144
+ See the JSON used to create your tables:
145
+
146
+ ```
147
+ rake eventosaurus:describe_tables
148
+ ```
149
+
150
+ If you decide to (╯°□°)╯︵ ┻━┻
151
+
152
+ ```
153
+ rake eventosaurus:drop_tables
154
+ ```
155
+
156
+ ## Storing Data
157
+
158
+ To store data use the `.store` class method on your event class. Use the same signature as your `details` method mentioned above:
159
+
160
+ ```ruby
161
+ # Somewhere in your app:
162
+ def check_for_audit(row)
163
+ if audit_time?
164
+ Events::CoreCustomerAudit.store(
165
+ updated_row: row,
166
+ updated_attribute: 'first_name',
167
+ updated_by_user_id: 35,
168
+ audit_occurred_at: UTC.now
169
+ )
170
+ end
171
+ end
172
+ ```
173
+
174
+ ## Querying Data
175
+
176
+ The gem gives you some dynamic methods to query your data based on your table definition. It's important to keep in mind that you are working with DynamoDB. It is not meant to be a data store that is accessed generically. It expects you to know the queries you want to run upfront. Good for us, we are storing each event type in its own table, so we can make good guesses about this. To this end, eventosaurus creates getters for the attributes you listed in your table definition:
177
+
178
+ ```ruby
179
+ Events::CoreCustomerAudit.by_customer_id(5)
180
+ Events::CoreCustomerAudit.by_customer_id(5).by_table_name('users').count
181
+
182
+ # event_uuid & created_at included for free :)
183
+ Events::CoreCustomerAudit.by_created_at('2015-01-04', 'GT')
184
+ ```
185
+
186
+ The queries above return eventosaurus Query objects. To actually execute the query, use the `run` method:
187
+
188
+ ```ruby
189
+ Events::CoreCustomerAudit.by_customer_id(5).count.run
190
+ ```
191
+
192
+ Note:
193
+
194
+ 0. In the last example we query by created_at even though it was not listed in the table definition. This is because each table gets the created_at timestamp column as well as the event_uuid column added.
195
+ 1. The operator defaults to 'EQ' (equals) but there are many to choose from: EQ, NE, IN, LE, LT, GE, GT, CONTAINS, NOT_CONTAINS, BEGINS_WITH
196
+ 2. DynamoDB only allows a **single** secondary index to accompany the partition key. This means the following query will not work the way you think:
197
+
198
+ ```
199
+ # too many secondary predicates. after one secondary index is used, the rest will be full scans on whatever comes back after the first local index.
200
+ Events::CoreCustomerAudit.by_created_at('2015-01-04', 'GT').by_table_name('users')
201
+ ```
202
+
203
+ **To sum it up: for speed, you are allowed 0||1 partition key condition and 0||1 secondary condition. No more than that.**
204
+
205
+ ## Test mode
206
+
207
+ Test mode can be enabled by placing the following in rails_helper.rb (or equivalent):
208
+
209
+ ```ruby
210
+ Eventosaurus.enable_test_mode
211
+ ```
212
+
213
+ ## On Choosing the proper table_definition for your event
214
+
215
+ When considering the correct partition_key, there are a few considerations. The first is to consider the predicates you will filter by. The predicates you use the most should probably become your partition_key. The second is the number of different values you expect to see in your partition. The more you have, the better. This is a complicated subject, and understanding of how DynamoDB works (partion keys, local and global secondary indexes) should be understood before creating an event. [Here][dynamodbbestpractices] you can find more detail about best practices, and of course hopefully a co-worker Near You can help too.
216
+
217
+ ## Event Error Handling upon calling .store
218
+
219
+ When you call `.store`, you will be utilizing your `.details` method. Sadly, sometimes you will make mistakes and the gem will raise. Happily, you can decide what to do about the errors. If your call to `.store` raises, the `on_error` class method is called with the error as an argument. Feel free to overwrite this class method in your Event class:
220
+
221
+ ```ruby
222
+ module Events
223
+ class NeatEvent
224
+ include Eventosaurus::Storable
225
+
226
+ # ... your primary event code here...
227
+
228
+ def on_error(error)
229
+ HaikuNotifier.write_haiku_with_error(error)
230
+ end
231
+ end
232
+ end
233
+ ```
234
+
235
+ ## Event Duplication Prevention
236
+
237
+ This gem has two methods of preventing duplicate events from being written to DynamoDB, and each method addresses a different way duplication can occur.
238
+
239
+
240
+ ### Background on the event_uuid column
241
+
242
+ Before getting into the two methods below, the foundational piece of information is that DynamoDB writes can be configured to fail if a duplicate value is found on an attribute. The Event Gem leverages this by using an 'event_uuid' as the table's sort key, and setting our writes to fail if the event_uuid already exists.
243
+
244
+ ### Duplication Cause 1: Double processing of asynchronous jobs.
245
+
246
+ If the same job that sends an event to dynamodb gets run twice, we need to make sure we don't store two events. This is handled by the mechanism explained above: writes are instructed to fail if they see the event_uuid already exists.
247
+
248
+ ### Duplication Cause 2: Gem client erroneously calls the .store method multiple times
249
+
250
+ If your (the gem client's) code has an error, and your code calls Events::NeatEvent.store more than intended, the Event Gem can be configured to help defend and ensure only 1 event is stored. To guard against this, you can create a composite primary key, based on the fields of your choosing. This composite key is then digested and used as the basis of the event_uuid. You may use the macro `compsite_primary_key` to achieve this duplication defense:
251
+
252
+
253
+ ```ruby
254
+ module Events
255
+ class NeatEvent
256
+
257
+ composite_primary_key :location, :employee_name, :employee_action
258
+ end
259
+ ```
260
+
261
+ The above example will cause a string like the following to be generated and used as a digest for the event_uuid:
262
+
263
+ ```
264
+ location=gardens:employee_name=Markus:employee_action=ate grapes
265
+ ```
266
+
267
+ Even if you call Events::NeatEvent.store(args) multiple times with the same args, only one event will be created.
268
+
269
+ If you do not opt to use the composite_primary_key feature, the Event Gem will use `SecureRandom.uuid` to generate the uuid, which has a much less likely chance of collision than you winning the lottery (It follows RFC 4122)
270
+
271
+ #### Do not add the created_at attr to your list of composite_primary_key attrs
272
+
273
+ Using a timestamp representing the creation-time of the event (aka the created_at attr) in the composite_primary_key is not advisable, as accidental duplicate events might have slightly different timestamps, and thus slightly different UUIDs. Put simply: _do not add the created_at attr to your list of composite_primary_key attrs._
274
+
275
+ **Note** that any attribute listed in the composite_primary_key macro promotes that attribute to a required attribute.
276
+
277
+
278
+ ## Using the AWS SDK (V2) Client Directly
279
+
280
+ To access the [Aws SDK v2 client][awssdkv2] directly (for educational purposes only), access via `Eventosaurus.configuration.dynamodb_client`. For example:
281
+
282
+ ```ruby
283
+ Eventosaurus.configuration.dynamodb_client.list_tables
284
+ ```
285
+
286
+ ## Development
287
+
288
+ 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.
289
+
290
+ ## Releasing
291
+
292
+ Version bumps should be done straight in master after appropriate PRs are merged.
293
+
294
+ Gem release best practices [here](https://github.com/blueapron/guides/blob/master/best_practices/developing_ruby_gems.md)
295
+
296
+ ## Contributing
297
+
298
+ Bug reports and pull requests are welcome on GitHub at https://github.com/blueapron/eventosaurus.
299
+
300
+ ## License
301
+
302
+ The gem is Copyright 2015 Blue Apron, Inc.
303
+
304
+ [dynamodbbestpractices]: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html#GuidelinesForTables.UniformWorkload
305
+ [dynamodb]: https://aws.amazon.com/dynamodb/
306
+ [localdynamo]: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tools.DynamoDBLocal.html
307
+ [awssdkv2]: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html
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/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "eventosaurus"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
8
+
9
+ echo -e "\n************************************************************\n"
10
+ echo -e "Install a local DynamoDB server: "
11
+ echo -e "http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tools.DynamoDBLocal.html"
12
+ echo -e "\n************************************************************\n"
data/circle.yml ADDED
@@ -0,0 +1,6 @@
1
+ dependencies:
2
+ pre:
3
+ - gem update bundler
4
+ test:
5
+ pre:
6
+ - bundle exec rubocop -D -fp
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'eventosaurus/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'eventosaurus'
8
+ spec.version = Eventosaurus::VERSION
9
+ spec.authors = ['Blue Apron Engineering']
10
+ spec.email = ['engineering@blueapron.com']
11
+
12
+ spec.summary = %q{Enables easy reporting of events to an event store.}
13
+ spec.description = %q{Enables easy reporting of events to an event store.}
14
+ spec.homepage = 'https://github.com/blueapron/eventosaurus'
15
+
16
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.bindir = 'bin'
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'activesupport'
24
+ spec.add_dependency 'aws-sdk', '~> 2.0'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.10'
27
+ spec.add_development_dependency 'pry'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rspec'
30
+ spec.add_development_dependency 'rubocop'
31
+ spec.add_development_dependency 'sidekiq'
32
+ spec.add_development_dependency 'simplecov'
33
+ spec.add_development_dependency 'timecop'
34
+
35
+ if ENV['CIRCLECI']
36
+ spec.add_development_dependency 'codeclimate-test-reporter'
37
+ spec.add_development_dependency 'rspec_junit_formatter'
38
+ end
39
+ end
@@ -0,0 +1,82 @@
1
+ require 'aws-sdk'
2
+
3
+ module Eventosaurus
4
+ class << self
5
+ attr_accessor :configuration
6
+
7
+ def configure
8
+ yield(configuration) if block_given?
9
+
10
+ configuration.configure_aws
11
+ configuration.configure_dynamodb
12
+ end
13
+
14
+ def configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def enable_test_mode
19
+ Storable::ClassMethods.redefine_method(:store) do
20
+ true
21
+ end
22
+
23
+ Models::Query.redefine_method(:run) do
24
+ true
25
+ end
26
+ end
27
+ end
28
+
29
+ class Configuration
30
+ attr_accessor :aws_access_key_id
31
+ attr_accessor :aws_endpoint
32
+ attr_accessor :aws_secret_access_key
33
+ attr_accessor :aws_region
34
+ attr_accessor :environment_prefix
35
+ attr_accessor :dynamodb_client
36
+ attr_accessor :dynamodb_table_namespace
37
+ attr_accessor :dynamodb_warn_on_scan
38
+ attr_accessor :logger
39
+ attr_accessor :persistor
40
+
41
+ def initialize
42
+ @logger = Logger.new(STDOUT)
43
+ end
44
+
45
+ def use_synchronous
46
+ require 'eventosaurus/persistors/synchronous'
47
+
48
+ @persistor = Eventosaurus::Persistors::Synchronous
49
+ end
50
+
51
+ def use_sidekiq
52
+ require 'eventosaurus/persistors/sidekiq'
53
+
54
+ @persistor = Eventosaurus::Persistors::Sidekiq
55
+ end
56
+
57
+ def configure_aws
58
+ Aws.config.update(region: aws_region, credentials: aws_credentials)
59
+ end
60
+
61
+ def aws_credentials
62
+ self.aws_region ||= 'us-east-2'
63
+ self.aws_access_key_id ||= 'unset'
64
+ self.aws_secret_access_key ||= 'unset'
65
+
66
+ @aws_credientials ||= Aws::Credentials.new(aws_access_key_id, aws_secret_access_key)
67
+ end
68
+
69
+ def configure_dynamodb
70
+ self.environment_prefix ||= 'unset'
71
+
72
+ args = {
73
+ region: aws_region,
74
+ credentials: aws_credentials
75
+ }
76
+
77
+ args[:endpoint] = aws_endpoint if aws_endpoint.present?
78
+
79
+ self.dynamodb_client = Aws::DynamoDB::Client.new(args)
80
+ end
81
+ end
82
+ end