active_record_serverless 0.1.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 +7 -0
- data/README.md +41 -0
- data/Rakefile +2 -0
- data/lib/active_record_serverless.rb +10 -0
- data/lib/active_record_serverless/executor.rb +17 -0
- data/lib/active_record_serverless/installer.rb +53 -0
- data/lib/active_record_serverless/logger.rb +9 -0
- data/lib/active_record_serverless/middleware/ensure_connection.rb +20 -0
- data/lib/active_record_serverless/railtie.rb +13 -0
- data/lib/active_record_serverless/reconnect.rb +16 -0
- data/lib/active_record_serverless/timeout.rb +69 -0
- data/lib/active_record_serverless/version.rb +3 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 52554bbe78950b6e39d662452b8f665a24dfd0c15edfccc8c7a2822a4a7fd0d0
|
4
|
+
data.tar.gz: 84848ac174145998e5a480a99727531d634ec10cb85fde8d5fdbba7f8707a0c7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 12ccacf518f299a27e3035176e421e1751f300bcce1a7dbe1f0c1e1128500c19e35d31cc51c8b75d0eb816d6f8570b2e2a15484b5fb0e58aecaff793493a6ba4
|
7
|
+
data.tar.gz: e72a10dd5ff32e5b1a5b5d286c767ad8142541c08e2e343b4e0fb1f5cb2281f919911f2882e18e53a472448d9e7793a6405909c66fbc93f8661e38bb03c22f89
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# ActiveRecordServerless
|
2
|
+
|
3
|
+
Handles database connection's to disconnect on a timeout. This allows [Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/) servers to spin down.
|
4
|
+
|
5
|
+
## Installing
|
6
|
+
|
7
|
+
In a Gemfile
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'active_record_serverless'
|
11
|
+
```
|
12
|
+
|
13
|
+
Manually
|
14
|
+
|
15
|
+
`gem install active_record_serverless`
|
16
|
+
|
17
|
+
### Config
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
# in config/database.yml
|
21
|
+
development:
|
22
|
+
# other db params
|
23
|
+
serverless:
|
24
|
+
timeout: 60.0 # Timeout every 60 seconds.
|
25
|
+
```
|
26
|
+
|
27
|
+
### Forking
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
after_fork do
|
31
|
+
ActiveRecordServerless.start_timeout
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
### Non-Rails Application.
|
36
|
+
|
37
|
+
#### Setup
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
ActiveRecordServerless::Installer.install!(nil)
|
41
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'active_record_serverless/installer'
|
2
|
+
require 'active_record_serverless/reconnect'
|
3
|
+
require 'active_record_serverless/timeout'
|
4
|
+
require 'active_record_serverless/version'
|
5
|
+
|
6
|
+
require 'active_record_serverless/railtie' if defined?(::Rails)
|
7
|
+
|
8
|
+
module ActiveRecordServerless
|
9
|
+
class Error < StandardError; end
|
10
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'timeout'
|
2
|
+
|
3
|
+
module ActiveRecordServerless
|
4
|
+
class Executor
|
5
|
+
def self.setup
|
6
|
+
ActiveRecord::Base.connection.class.class_eval do
|
7
|
+
alias_method :serverless_execute, :execute
|
8
|
+
|
9
|
+
def execute(*args)
|
10
|
+
ActiveRecordServerless::Timeout.touch!
|
11
|
+
|
12
|
+
serverless_execute(*args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
require_relative 'timeout'
|
4
|
+
require_relative 'logger'
|
5
|
+
require_relative 'executor'
|
6
|
+
|
7
|
+
module ActiveRecordServerless
|
8
|
+
def self.start_timeout(timeout = nil)
|
9
|
+
ActiveRecordServerless::Installer.start_timeout(timeout)
|
10
|
+
end
|
11
|
+
|
12
|
+
class Installer
|
13
|
+
class << self
|
14
|
+
def config
|
15
|
+
ActiveRecord::Base.connection_config.with_indifferent_access.dig(:serverless)
|
16
|
+
end
|
17
|
+
|
18
|
+
def install!(_app)
|
19
|
+
disabled = config.dig(:disabled).nil? ? false : config.dig(:disabled)
|
20
|
+
|
21
|
+
if disabled == true
|
22
|
+
message = <<~EOF
|
23
|
+
Skipping ActiveRecordServerless Install.
|
24
|
+
|
25
|
+
Connection config explicitly marked serverless as disabled.
|
26
|
+
EOF
|
27
|
+
ActiveRecordServerless.log(message)
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
_install
|
32
|
+
end
|
33
|
+
|
34
|
+
def start_timeout(timeout = nil)
|
35
|
+
timeout ||= (config.dig(:timeout) || 60.0)
|
36
|
+
|
37
|
+
ActiveRecordServerless.log("Installing ActiveRecordServerless [timeout=#{timeout}]")
|
38
|
+
|
39
|
+
ActiveRecordServerless::Timeout.on_timeout(timeout) do
|
40
|
+
ActiveRecordServerless.log('ActiveRecordServerless timeout...')
|
41
|
+
ActiveRecord::Base.connection_pool.disconnect!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def _install
|
48
|
+
ActiveRecordServerless::Executor.setup
|
49
|
+
ActiveRecordServerless::Installer.start_timeout
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
require_relative '../timeout'
|
4
|
+
|
5
|
+
module ActiveRecordServerless
|
6
|
+
module Middleware
|
7
|
+
class EnsureConnection
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
ActiveRecordServerless::Timeout.touch! do
|
14
|
+
ActiveRecord::Base.establish_connection unless ActiveRecord::Base.connected?
|
15
|
+
end
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
require_relative 'installer'
|
4
|
+
require_relative 'middleware/ensure_connection'
|
5
|
+
|
6
|
+
module ActiveRecordServerless
|
7
|
+
class Railtie < ::Rails::Railtie
|
8
|
+
initializer 'active_record_serverless.install', after: 'active_record.initialize_database' do |app|
|
9
|
+
ActiveRecordServerless::Installer.install!(app)
|
10
|
+
app.middleware.insert_before(Rack::Runtime, ActiveRecordServerless::Middleware::EnsureConnection)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support'
|
3
|
+
|
4
|
+
require_relative 'timeout'
|
5
|
+
|
6
|
+
module ActiveRecordServerless
|
7
|
+
def self.reconnect
|
8
|
+
ActiveRecordServerless::Timeout.touch!
|
9
|
+
|
10
|
+
return if ActiveRecord::Base.connected?
|
11
|
+
|
12
|
+
ActiveSupport::Notifications.instrument('active_record_serverless.reconnect') do
|
13
|
+
ActiveRecord::Base.establish_connection
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module ActiveRecordServerless
|
4
|
+
class Timeout
|
5
|
+
MUTEX = Mutex.new
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def touch!
|
9
|
+
ActiveSupport::Notifications.instrument('active_record_serverless.touch') do
|
10
|
+
MUTEX.synchronize do
|
11
|
+
_last_used(Time.now)
|
12
|
+
yield if block_given?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def last_used
|
18
|
+
MUTEX.synchronize { _last_used }
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_timeout(timeout, &block)
|
22
|
+
raise ArgumentError, 'Timeout must be greater than 1' unless timeout.to_f >= 1.0
|
23
|
+
|
24
|
+
touch!
|
25
|
+
|
26
|
+
MUTEX.synchronize do
|
27
|
+
_running_id((_running_id || 0) + 1)
|
28
|
+
end
|
29
|
+
|
30
|
+
_on_timeout(timeout.to_f, running_id, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def running?
|
34
|
+
running_id.positive?
|
35
|
+
end
|
36
|
+
|
37
|
+
def running_id
|
38
|
+
MUTEX.synchronize { _running_id }
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def _on_timeout(timeout, rid, &block)
|
44
|
+
Thread.new do
|
45
|
+
sleep(timeout)
|
46
|
+
last = last_used
|
47
|
+
delta = Time.now.to_f - last.to_f
|
48
|
+
if delta >= timeout
|
49
|
+
opts = { last_time: last, delta: delta, running_id: rid }
|
50
|
+
ActiveSupport::Notifications.instrument('active_record_serverless.timeout', opts) do
|
51
|
+
yield(last, delta)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
_on_timeout(timeout, rid, &block) if rid == running_id
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def _last_used(time = nil)
|
59
|
+
@_last_used = time unless time.nil?
|
60
|
+
@_last_used
|
61
|
+
end
|
62
|
+
|
63
|
+
def _running_id(running = nil)
|
64
|
+
@_running_id = running unless running.nil?
|
65
|
+
@_running_id
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_record_serverless
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maddie Schipper
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.0.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 4.0.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: activesupport
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 4.0.0
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '7.0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 4.0.0
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '7.0'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: bundler
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.0'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '2.0'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: pry
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.12'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0.12'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rake
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '10.0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '10.0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: rspec-rails
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '3.8'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '3.8'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: simplecov
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0.16'
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0.16'
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: sqlite3
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '1.3'
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '1.3'
|
137
|
+
description: ActiveRecord Serverless handle AWS Aurora Serverless
|
138
|
+
email:
|
139
|
+
- me@maddiesch.com
|
140
|
+
executables: []
|
141
|
+
extensions: []
|
142
|
+
extra_rdoc_files: []
|
143
|
+
files:
|
144
|
+
- README.md
|
145
|
+
- Rakefile
|
146
|
+
- lib/active_record_serverless.rb
|
147
|
+
- lib/active_record_serverless/executor.rb
|
148
|
+
- lib/active_record_serverless/installer.rb
|
149
|
+
- lib/active_record_serverless/logger.rb
|
150
|
+
- lib/active_record_serverless/middleware/ensure_connection.rb
|
151
|
+
- lib/active_record_serverless/railtie.rb
|
152
|
+
- lib/active_record_serverless/reconnect.rb
|
153
|
+
- lib/active_record_serverless/timeout.rb
|
154
|
+
- lib/active_record_serverless/version.rb
|
155
|
+
homepage: https://github.com/maddiesch/active_record_serverless
|
156
|
+
licenses:
|
157
|
+
- MIT
|
158
|
+
metadata: {}
|
159
|
+
post_install_message:
|
160
|
+
rdoc_options: []
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
requirements: []
|
174
|
+
rubygems_version: 3.0.2
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: ActiveRecord Serverless handle AWS Aurora Serverless
|
178
|
+
test_files: []
|