bleib 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1a34d27aee38f1710132dd474bc51bf4e2653b0b
4
+ data.tar.gz: 99174d377d7b00fbcafbcb2e834131926de04b73
5
+ SHA512:
6
+ metadata.gz: ce8c1536ee576b3d8b3fe5448e01ea0f92558688af1c746234e7042795be081a7c1329a768634c82d3ea13b4aa348d524e4893fafd47d73c317e668448d6e508
7
+ data.tar.gz: 88ad1141821e37b1575c4e0aa4a17f6e42815a8acf34950175ac3563d19e846cce271a043dcc293b0c7665c2d3f2f8be906a2425226c237d15b438c71300e4fa
@@ -0,0 +1,10 @@
1
+ require 'bleib/version'
2
+
3
+ require 'bleib/railtie' if defined?(Rails)
4
+
5
+ require 'bleib/configuration'
6
+ require 'bleib/database'
7
+ require 'bleib/migrations'
8
+
9
+ module Bleib
10
+ end
@@ -0,0 +1,94 @@
1
+ module Bleib
2
+ class Configuration
3
+ class UnsupportedAdapterException < Exception; end
4
+ class DatabaseYmlNotFoundException < Exception; end
5
+
6
+ attr_reader :database, :check_database_interval, :check_migrations_interval
7
+
8
+ DEFAULT_CHECK_DATABASE_INTERVAL = 5 # Seconds
9
+ DEFAULT_CHECK_MIGRATIONS_INTERVAL = 5 # Seconds
10
+ DEFAULT_DATABASE_YML_PATH = 'config/database'
11
+
12
+ def self.from_environment
13
+ check_database_interval = interval_or_default(
14
+ ENV['BLEIB_CHECK_DATABASE_INTERVAL'],
15
+ DEFAULT_CHECK_DATABASE_INTERVAL
16
+ )
17
+ check_migrations_interval = interval_or_default(
18
+ ENV['BLEIB_CHECK_MIGRATIONS_INTERVAL'],
19
+ DEFAULT_CHECK_MIGRATIONS_INTERVAL
20
+ )
21
+
22
+ database_yml_path = ENV['BLEIB_DATABASE_YML_PATH']
23
+ database_yml_path ||= File.expand_path('config/database.yml')
24
+ ensure_database_yml!(database_yml_path)
25
+
26
+ rails_env = ENV['RAILS_ENV'] || 'development'
27
+
28
+ new(
29
+ rails_database(database_yml_path, rails_env),
30
+ check_database_interval: check_database_interval.to_i,
31
+ check_migrations_interval: check_migrations_interval.to_i
32
+ )
33
+ end
34
+
35
+ def initialize(database_configuration,
36
+ check_database_interval: DEFAULT_CHECK_DATABASE_INTERVAL,
37
+ check_migrations_interval: DEFAULT_CHECK_MIGRATIONS_INTERVAL)
38
+ # To be 100% sure which connection the
39
+ # active record pool creates, returns or removes.
40
+ only_one_connection = { 'pool' => 1 }
41
+
42
+ @database = database_configuration.merge(only_one_connection)
43
+
44
+ @check_database_interval = check_database_interval
45
+ @check_migrations_interval = check_migrations_interval
46
+
47
+ check!
48
+ end
49
+
50
+ def logger
51
+ return @logger unless @logger.nil?
52
+
53
+ @logger = Logger.new(STDOUT)
54
+ @logger.level = if ENV['BLEIB_LOG_LEVEL'] == 'debug'
55
+ Logger::DEBUG
56
+ else
57
+ Logger::INFO
58
+ end
59
+ @logger
60
+ end
61
+
62
+ private
63
+
64
+ def self.interval_or_default(string, default)
65
+ given = string.to_i
66
+ given <= 0 ? default : given
67
+ end
68
+
69
+ def self.ensure_database_yml!(path)
70
+ return if File.exist?(path)
71
+
72
+ fail DatabaseYmlNotFoundException,
73
+ 'database.yml not found, set or fix' \
74
+ ' BLEIB_DATABASE_YML_PATH or execute me' \
75
+ ' from the rails root.'
76
+ end
77
+
78
+ def self.rails_database(database_yml_path, rails_env)
79
+ contents = File.read(database_yml_path)
80
+ config = YAML.load(ERB.new(contents).result)
81
+ config[rails_env]
82
+ end
83
+
84
+ def check!
85
+ # We should add clean rescue statements to
86
+ # `Bleib::Database#database_down?`to support
87
+ # other adapters.
88
+ if @database['adapter'] != 'postgresql'
89
+ fail UnsupportedAdapterException,
90
+ "Unknown database adapter #{@database['adapter']}"
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,73 @@
1
+ module Bleib
2
+ # Finds out if a database is running and accessible.
3
+ #
4
+ # Does so by using ActiveRecord without a booted rails
5
+ # environment (because a non-accessible database can
6
+ # cause the bootup to fail).
7
+ class Database
8
+ def initialize(configuration)
9
+ @configuration = configuration
10
+ end
11
+
12
+ def wait_for_connection
13
+ logger.info('Waiting for connection to database')
14
+
15
+ wait while database_down?
16
+
17
+ logger.info('Connection to database established')
18
+
19
+ # Nobody else shall use our single-connection pool.
20
+ remove_connection
21
+ end
22
+
23
+ private
24
+
25
+ def wait
26
+ duration = @configuration.check_database_interval
27
+
28
+ logger.debug "Waiting for #{duration} seconds"
29
+
30
+ sleep(duration)
31
+ end
32
+
33
+ def database_down?
34
+ logger.debug('Checking database')
35
+
36
+ # Adopted from the default OpenShift readiness check for postgresql.
37
+ ActiveRecord::Base.establish_connection(@configuration.database)
38
+ ActiveRecord::Base.connection.execute('SELECT 1;')
39
+
40
+ logger.debug('Database check succeeded')
41
+
42
+ false
43
+ rescue PG::ConnectionBad => e
44
+ # On stopped database:
45
+ # PG::ConnectionBad: could not connect to server: Connection refused
46
+ # Is the server running on host "127.0.0.1" and accepting
47
+ # TCP/IP connections on port 5432?
48
+ # On wrong/missing user:
49
+ # PG::ConnectionBad: FATAL: password authentication failed for user "wrong"
50
+ # On wrong password:
51
+ # PG::ConnectionBad: FATAL: password authentication failed for user "user"
52
+
53
+ logger.debug("Database check failed: #{e}")
54
+
55
+ true
56
+ rescue ActiveRecord::NoDatabaseError
57
+ # On missing database:
58
+ # ActiveRecord::NoDatabaseError: FATAL: database "wrong" does not exist
59
+
60
+ logger.debug("Database check failed: #{e}")
61
+
62
+ true
63
+ end
64
+
65
+ def remove_connection
66
+ ActiveRecord::Base.remove_connection
67
+ end
68
+
69
+ def logger
70
+ @configuration.logger
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,71 @@
1
+ module Bleib
2
+ # Finds out if all migrations are up.
3
+ #
4
+ # Knows how to handle multitenancy with Apartment, if used.
5
+ class Migrations
6
+ def initialize(configuration)
7
+ @configuration = configuration
8
+ end
9
+
10
+ def wait_until_done
11
+ logger.info('Waiting for migrations' \
12
+ ' (Also checking apartment tenants:' \
13
+ " #{apartment_gem? ? 'yes' : 'no'})")
14
+
15
+ wait while pending_migrations?
16
+
17
+ logger.info('All migrations are up')
18
+ end
19
+
20
+ private
21
+
22
+ def wait
23
+ duration = @configuration.check_migrations_interval
24
+
25
+ logger.debug "Waiting for #{@configuration.check_migrations_interval} seconds"
26
+
27
+ sleep(duration)
28
+ end
29
+
30
+ def pending_migrations?
31
+ logger.debug('Checking migrations')
32
+
33
+ if apartment_gem?
34
+ in_all_tenant_contexts { check_migrations! }
35
+ else
36
+ check_migrations!
37
+ end
38
+
39
+ logger.debug('Migrations check succeeded.')
40
+
41
+ false
42
+ rescue ActiveRecord::PendingMigrationError
43
+ logger.debug('Migrations pending, check failed')
44
+
45
+ true
46
+ end
47
+
48
+ def apartment_gem?
49
+ defined?(Apartment::Tenant)
50
+ end
51
+
52
+ def check_migrations!
53
+ ActiveRecord::Migration.check_pending!
54
+ end
55
+
56
+ def in_all_tenant_contexts
57
+ tenants = ['public']
58
+ Apartment::Tenant.each { |tenant| tenants << tenant }
59
+
60
+ tenants.each do |tenant|
61
+ Apartment::Tenant.switch(tenant) do
62
+ yield
63
+ end
64
+ end
65
+ end
66
+
67
+ def logger
68
+ @configuration.logger
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,7 @@
1
+ module Bleib
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load 'tasks/bleib.rake'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Bleib
2
+ VERSION = '0.0.7'.freeze
3
+ end
@@ -0,0 +1,14 @@
1
+ namespace :bleib do
2
+ desc 'Waits for database access'
3
+ task :wait_for_database do
4
+ configuration = Bleib::Configuration.from_environment
5
+ Bleib::Database.new(configuration).wait_for_connection
6
+ end
7
+
8
+ desc 'Waits for database access and migrations'
9
+ task wait_for_migrations: [:wait_for_database, :environment] do
10
+ configuration = Bleib::Configuration.from_environment
11
+
12
+ Bleib::Migrations.new(configuration).wait_until_done
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bleib
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Puzzle ITC
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-10-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Intended for use in containerized setups whereanother component takes
14
+ care of migrating the database.
15
+ email: raez@puzzle.ch
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/bleib.rb
21
+ - lib/bleib/configuration.rb
22
+ - lib/bleib/database.rb
23
+ - lib/bleib/migrations.rb
24
+ - lib/bleib/railtie.rb
25
+ - lib/bleib/version.rb
26
+ - lib/tasks/bleib.rake
27
+ homepage: http://rubygems.org/gems/bleib
28
+ licenses:
29
+ - MIT
30
+ metadata:
31
+ source_code_uri: https://github.com/puzzle/bleib
32
+ documentation_uri: https://github.com/puzzle/bleib
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.4.8
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: Use a rake task to wait on database and migrations.
53
+ test_files: []
54
+ has_rdoc: