bleib 0.0.7

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.
@@ -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: