phobos_db_checkpoint 0.2.0 → 0.3.0

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
  SHA1:
3
- metadata.gz: 5b5b26c404a1ef381a22acb11321da68ff796a07
4
- data.tar.gz: f70ffacba27f60a03be78c40caef88af565d61b0
3
+ metadata.gz: bf7c86a517c50d731d343b8cbf72f7fcacd413a4
4
+ data.tar.gz: ca87a4ce8ce804edcfdbc6cbc991404730bc8524
5
5
  SHA512:
6
- metadata.gz: e06985bb11ffc04fb94e00dcbedb158aa423643958e50cef89645e9dbf80c03bc7af391323c1483e32f9770deec18e27b1ba48a10fd1ac4537edcd4995c68a54
7
- data.tar.gz: f152ff0bc835ee77cb10f9ba5c238eaaef7d33abea0556ded954ed30ea65fe8fe54a727a4672aadf4084ac868c14866894c47ad541a4ba6a09633a1272bcebf5
6
+ metadata.gz: dab2ad650f6fe21d495ac3a6d2f8645907d17e39299c509c48f95f7f0005af4d88887b63b1a2a41f959f213626de8550159d6a8b1b14a04b043f7e0a95dfde0e
7
+ data.tar.gz: 6ac30e2f38f7d54e9ec1dd44266f113872deadd8f53aedfcded766a60096ce9aff0c7ef527aea866ba479f71dd697a8e96a762c7e9b72ab969574bc29bf903e0
data/.gitignore CHANGED
@@ -13,3 +13,5 @@ spec/examples.txt
13
13
  spec/setup/
14
14
  spec/tmp/
15
15
  .byebug_history
16
+ log/
17
+ spec/log/
data/CHANGELOG.md CHANGED
@@ -4,12 +4,19 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## 0.3.0 (2016-10-10)
8
+
9
+ - [feature] Built-in sinatra APP with events API
10
+
7
11
  ## 0.2.0 (2016-09-06)
12
+
8
13
  - [feature] New CLI command to generate migrations #6
9
14
  - [feature] Automatically sets database pool size based on listeners max_concurrency #2
10
15
 
11
16
  ## 0.1.1 (2016-09-02)
17
+
12
18
  - [bugfix] Handler is not injecting start and stop methods #4
13
19
 
14
20
  ## 0.1.0 (2016-08-29)
21
+
15
22
  - Published on Github
data/README.md CHANGED
@@ -15,6 +15,7 @@ Phobos DB Checkpoint is a plugin to [Phobos](https://github.com/klarna/phobos) a
15
15
  1. [Setup](#setup)
16
16
  1. [Handler](#handler)
17
17
  1. [Accessing the events](#accessing-the-events)
18
+ 1. [Events API](#events-api)
18
19
  1. [Instrumentation](#instrumentation)
19
20
  1. [Development](#development)
20
21
 
@@ -122,6 +123,46 @@ Note that the `PhobosDBCheckpoint::Handler` will automatically skip already hand
122
123
 
123
124
  `PhobosDBCheckpoint::Event` is a plain `ActiveRecord::Base` model, feel free to play with it.
124
125
 
126
+ ### <a name="events-api"></a> Events API
127
+
128
+ Phobos DB Checkpoint comes with a sinatra app which makes the event manipulation easy through its JSON API.
129
+
130
+ The __init_events_api__ command will generate a `config.ru` ready to use:
131
+
132
+ ```sh
133
+ $ phobos_db_checkpoint init_events_api
134
+ create config.ru
135
+ Start the API with: `rackup config.ru`
136
+ ```
137
+
138
+ ```sh
139
+ $ curl "http://localhost:9292/v1/events/1"
140
+ # {
141
+ # "id": 1,
142
+ # "topic": "test-partitions",
143
+ # "group_id": "test-checkpoint-1",
144
+ # "entity_id": "1",
145
+ # "event_time": "2016-09-19T19:35:26.854Z",
146
+ # "event_type": "create",
147
+ # "event_version": "v1",
148
+ # "checksum": "188773471ec0f898fd81d272760a027f",
149
+ # "payload": "{\"a\":\"b\"}"
150
+ # }
151
+ ```
152
+
153
+ The available routes are:
154
+
155
+ * GET `/ping`
156
+ * GET `/v1/events/:id`
157
+ * GET `/v1/events` This route accepts the following params:
158
+ * `limit`, default: 20
159
+ * `offset`, default: 0
160
+ * `entity_id`
161
+ * `topic`
162
+ * `group_id`
163
+ * `event_type`
164
+ * POST `/v1/events/:id/retry`
165
+
125
166
  ### <a name="instrumentation"></a> Instrumentation
126
167
 
127
168
  Some operations are instrumented using [Phobos::Instrumentation](https://github.com/klarna/phobos#usage-instrumentation)
@@ -12,13 +12,14 @@ module PhobosDBCheckpoint
12
12
  DEFAULT_DB_DIR = 'db'.freeze
13
13
  DEFAULT_MIGRATION_PATH = File.join(DEFAULT_DB_DIR, 'migrate').freeze
14
14
  DEFAULT_DB_CONFIG_PATH = 'config/database.yml'.freeze
15
+ DEFAULT_POOL_SIZE = 5.freeze
15
16
 
16
17
  class << self
17
18
  attr_reader :db_config
18
19
  attr_accessor :db_config_path, :db_dir, :migration_path
19
20
 
20
- def configure
21
- load_db_config
21
+ def configure(pool_size: nil)
22
+ load_db_config(pool_size: pool_size)
22
23
  at_exit { PhobosDBCheckpoint.close_db_connection }
23
24
  ActiveRecord::Base.establish_connection(db_config)
24
25
  end
@@ -27,15 +28,16 @@ module PhobosDBCheckpoint
27
28
  ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] ||= 'development'
28
29
  end
29
30
 
30
- def load_db_config
31
+ def load_db_config(pool_size: nil)
31
32
  @db_config_path ||= DEFAULT_DB_CONFIG_PATH
32
33
  configs = YAML.load_file(File.expand_path(@db_config_path))
33
34
  @db_config = configs[env]
34
35
 
35
- if Phobos.config
36
+ if pool_size.nil? && Phobos.config
36
37
  pool_size = Phobos.config.listeners.map { |listener| listener.max_concurrency || 1 }.inject(&:+)
37
- @db_config.merge!('pool' => pool_size)
38
38
  end
39
+
40
+ @db_config.merge!('pool' => pool_size || DEFAULT_POOL_SIZE)
39
41
  end
40
42
 
41
43
  def close_db_connection
@@ -66,6 +66,12 @@ module PhobosDBCheckpoint
66
66
  template(new_migration_template, destination_fullpath)
67
67
  end
68
68
 
69
+ desc 'init-events-api', 'Initialize your project with events API'
70
+ def init_events_api
71
+ copy_file 'templates/config.ru', 'config.ru'
72
+ say ' Start the API with: `rackup config.ru`'
73
+ end
74
+
69
75
  def self.source_root
70
76
  File.expand_path(File.join(File.dirname(__FILE__), '../..'))
71
77
  end
@@ -14,6 +14,14 @@ module PhobosDBCheckpoint
14
14
  save!
15
15
  end
16
16
 
17
+ def configured_handler
18
+ Phobos
19
+ .config
20
+ .listeners
21
+ .find { |listener| listener.group_id == self.group_id }
22
+ &.handler
23
+ end
24
+
17
25
  private
18
26
 
19
27
  def assign_checksum
@@ -0,0 +1,76 @@
1
+ require 'json'
2
+ require 'rack'
3
+ require 'sinatra/base'
4
+
5
+ require 'phobos_db_checkpoint/middleware/logger'
6
+ require 'phobos_db_checkpoint/middleware/database'
7
+
8
+ module PhobosDBCheckpoint
9
+ class EventsAPI < Sinatra::Base
10
+ VERSION = :v1
11
+ set :logging, nil
12
+
13
+ not_found do
14
+ content_type :json
15
+ { error: true, message: 'not found' }.to_json
16
+ end
17
+
18
+ error ActiveRecord::RecordNotFound do
19
+ content_type :json
20
+ status 404
21
+ { error: true, message: 'event not found' }.to_json
22
+ end
23
+
24
+ error StandardError do
25
+ content_type :json
26
+ error = env['sinatra.error']
27
+ { error: true, message: error.message }.to_json
28
+ end
29
+
30
+ get '/ping' do
31
+ 'PONG'
32
+ end
33
+
34
+ get "/#{VERSION}/events/:id" do
35
+ content_type :json
36
+ PhobosDBCheckpoint::Event
37
+ .find(params['id'])
38
+ .to_json
39
+ end
40
+
41
+ post "/#{VERSION}/events/:id/retry" do
42
+ content_type :json
43
+ event = PhobosDBCheckpoint::Event.find(params['id'])
44
+ handler_name = event.configured_handler
45
+
46
+ unless handler_name
47
+ status 422
48
+ return { error: true, message: 'no handler configured for this event' }.to_json
49
+ end
50
+
51
+ handler_class = handler_name.constantize
52
+ metadata = { listener_id: 'events_api/retry', group_id: event.group_id, topic: event.topic, retry_count: 0 }
53
+ event_action = handler_class.new.consume(event.payload, metadata)
54
+
55
+ { acknowledged: event_action.is_a?(PhobosDBCheckpoint::Ack) }.to_json
56
+ end
57
+
58
+ get "/#{VERSION}/events" do
59
+ content_type :json
60
+ limit = (params['limit'] || 20).to_i
61
+ offset = (params['offset'] || 0).to_i
62
+
63
+ query = PhobosDBCheckpoint::Event
64
+ query = query.where(topic: params['topic']) if params['topic']
65
+ query = query.where(group_id: params['group_id']) if params['group_id']
66
+ query = query.where(entity_id: params['entity_id']) if params['entity_id']
67
+ query = query.where(event_type: params['event_type']) if params['event_type']
68
+
69
+ query
70
+ .order(event_time: :desc)
71
+ .limit(limit)
72
+ .offset(offset)
73
+ .to_json
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,20 @@
1
+ module PhobosDBCheckpoint
2
+ module Middleware
3
+ class Database
4
+
5
+ def initialize(app, options = {})
6
+ @app = app
7
+ pool_size = options.fetch(:pool_size, PhobosDBCheckpoint::DEFAULT_POOL_SIZE)
8
+ PhobosDBCheckpoint.configure(pool_size: pool_size)
9
+ end
10
+
11
+ def call(request_env)
12
+ ActiveRecord::Base.connection_pool.with_connection do
13
+ @app.call(request_env)
14
+ end
15
+ ensure
16
+ ActiveRecord::Base.clear_active_connections!
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,68 @@
1
+ require 'rack'
2
+
3
+ module PhobosDBCheckpoint
4
+ module Middleware
5
+ class Logger
6
+ RACK_LOGGER = 'rack.logger'.freeze
7
+ SINATRA_ERROR = 'sinatra.error'.freeze
8
+ HTTP_VERSION = 'HTTP_VERSION'.freeze
9
+ PATH_INFO = 'PATH_INFO'.freeze
10
+ REQUEST_METHOD = 'REQUEST_METHOD'.freeze
11
+ QUERY_STRING = 'QUERY_STRING'.freeze
12
+ CONTENT_LENGTH = 'Content-Length'.freeze
13
+
14
+ def initialize(app, options = {})
15
+ @app = app
16
+ Phobos.configure(options.fetch(:config, 'config/phobos.yml'))
17
+ Phobos.config.logger.file = options.fetch(:log_file, 'log/api.log')
18
+ Phobos.configure_logger
19
+ ActiveRecord::Base.logger = Phobos.logger
20
+ end
21
+
22
+ def call(request_env)
23
+ began_at = Time.now
24
+ request_env[RACK_LOGGER] = Phobos.logger
25
+ status, header, body = @app.call(request_env)
26
+ header = Rack::Utils::HeaderHash.new(header)
27
+ body = Rack::BodyProxy.new(body) do
28
+ log(request_env, status, header, began_at)
29
+ end
30
+ [status, header, body]
31
+ end
32
+
33
+ private
34
+
35
+ def log(request_env, status, header, began_at)
36
+ error = request_env[SINATRA_ERROR]
37
+ message = {
38
+ remote_address: request_env['HTTP_X_FORWARDED_FOR'] || request_env['REMOTE_ADDR'],
39
+ remote_user: request_env['REMOTE_USER'],
40
+ request_method: request_env[REQUEST_METHOD],
41
+ path: extract_path(request_env),
42
+ status: status.to_s[0..3],
43
+ content_length: extract_content_length(header),
44
+ request_time: "#{Time.now - began_at}s"
45
+ }
46
+
47
+ if error
48
+ Phobos.logger.error(message.merge(
49
+ exception_class: error.class.to_s,
50
+ exception_message: error.message,
51
+ backtrace: error.backtrace
52
+ ))
53
+ else
54
+ Phobos.logger.info(message)
55
+ end
56
+ end
57
+
58
+ def extract_path(request_env)
59
+ "#{request_env[PATH_INFO]}#{request_env[QUERY_STRING].empty? ? "" : "?#{request_env[QUERY_STRING]}"} #{request_env[HTTP_VERSION]}"
60
+ end
61
+
62
+ def extract_content_length(headers)
63
+ value = headers[CONTENT_LENGTH] or return
64
+ value.to_s == '0' ? nil : value
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,3 @@
1
1
  module PhobosDBCheckpoint
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -51,9 +51,11 @@ Gem::Specification.new do |spec|
51
51
  spec.add_development_dependency 'pg'
52
52
  spec.add_development_dependency 'database_cleaner'
53
53
  spec.add_development_dependency 'rspec_junit_formatter', '0.2.2'
54
+ spec.add_development_dependency 'rack-test'
54
55
 
55
56
  spec.add_dependency 'thor'
56
57
  spec.add_dependency 'rake'
57
58
  spec.add_dependency 'activerecord', '>= 4.0.0'
58
59
  spec.add_dependency 'phobos', '>= 1.0.0'
60
+ spec.add_dependency 'sinatra'
59
61
  end
@@ -0,0 +1,17 @@
1
+ require 'bundler/setup'
2
+ require 'phobos_db_checkpoint'
3
+ require 'phobos_db_checkpoint/events_api'
4
+ require_relative './phobos_boot.rb'
5
+
6
+ logger_config = {
7
+ # config: 'config/phobos.yml'
8
+ # log_file: 'log/api.log'
9
+ }
10
+
11
+ database_config = {
12
+ # pool_size: PhobosDBCheckpoint::DEFAULT_POOL_SIZE # 5
13
+ }
14
+
15
+ use PhobosDBCheckpoint::Middleware::Logger, logger_config
16
+ use PhobosDBCheckpoint::Middleware::Database, database_config
17
+ run PhobosDBCheckpoint::EventsAPI
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phobos_db_checkpoint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Túlio Ornelas
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2016-09-06 00:00:00.000000000 Z
16
+ date: 2016-10-10 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: bundler
@@ -141,6 +141,20 @@ dependencies:
141
141
  - - '='
142
142
  - !ruby/object:Gem::Version
143
143
  version: 0.2.2
144
+ - !ruby/object:Gem::Dependency
145
+ name: rack-test
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
144
158
  - !ruby/object:Gem::Dependency
145
159
  name: thor
146
160
  requirement: !ruby/object:Gem::Requirement
@@ -197,6 +211,20 @@ dependencies:
197
211
  - - ">="
198
212
  - !ruby/object:Gem::Version
199
213
  version: 1.0.0
214
+ - !ruby/object:Gem::Dependency
215
+ name: sinatra
216
+ requirement: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ version: '0'
221
+ type: :runtime
222
+ prerelease: false
223
+ version_requirements: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - ">="
226
+ - !ruby/object:Gem::Version
227
+ version: '0'
200
228
  description: Phobos DB Checkpoint is a plugin to Phobos and is meant as a drop in
201
229
  replacement to Phobos::Handler
202
230
  email:
@@ -226,10 +254,14 @@ files:
226
254
  - lib/phobos_db_checkpoint/cli.rb
227
255
  - lib/phobos_db_checkpoint/event.rb
228
256
  - lib/phobos_db_checkpoint/event_actions.rb
257
+ - lib/phobos_db_checkpoint/events_api.rb
229
258
  - lib/phobos_db_checkpoint/handler.rb
259
+ - lib/phobos_db_checkpoint/middleware/database.rb
260
+ - lib/phobos_db_checkpoint/middleware/logger.rb
230
261
  - lib/phobos_db_checkpoint/tasks.rb
231
262
  - lib/phobos_db_checkpoint/version.rb
232
263
  - phobos_db_checkpoint.gemspec
264
+ - templates/config.ru
233
265
  - templates/database.yml.example
234
266
  - templates/migrate/phobos_01_create_events.rb.erb
235
267
  - templates/new_migration.rb.erb