phobos_db_checkpoint 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +7 -0
- data/README.md +41 -0
- data/lib/phobos_db_checkpoint.rb +7 -5
- data/lib/phobos_db_checkpoint/cli.rb +6 -0
- data/lib/phobos_db_checkpoint/event.rb +8 -0
- data/lib/phobos_db_checkpoint/events_api.rb +76 -0
- data/lib/phobos_db_checkpoint/middleware/database.rb +20 -0
- data/lib/phobos_db_checkpoint/middleware/logger.rb +68 -0
- data/lib/phobos_db_checkpoint/version.rb +1 -1
- data/phobos_db_checkpoint.gemspec +2 -0
- data/templates/config.ru +17 -0
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf7c86a517c50d731d343b8cbf72f7fcacd413a4
|
4
|
+
data.tar.gz: ca87a4ce8ce804edcfdbc6cbc991404730bc8524
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dab2ad650f6fe21d495ac3a6d2f8645907d17e39299c509c48f95f7f0005af4d88887b63b1a2a41f959f213626de8550159d6a8b1b14a04b043f7e0a95dfde0e
|
7
|
+
data.tar.gz: 6ac30e2f38f7d54e9ec1dd44266f113872deadd8f53aedfcded766a60096ce9aff0c7ef527aea866ba479f71dd697a8e96a762c7e9b72ab969574bc29bf903e0
|
data/.gitignore
CHANGED
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)
|
data/lib/phobos_db_checkpoint.rb
CHANGED
@@ -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
|
@@ -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
|
@@ -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
|
data/templates/config.ru
ADDED
@@ -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.
|
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-
|
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
|