Class: ActiveRecord::ConnectionAdapters::PostgreSQL::Branched::BranchManager
- Inherits:
-
Object
- Object
- ActiveRecord::ConnectionAdapters::PostgreSQL::Branched::BranchManager
- Defined in:
- lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb
Constant Summary collapse
- MAX_SCHEMA_LENGTH =
63- PREFIX =
"branch_"
Instance Attribute Summary collapse
-
#branch ⇒ Object
readonly
Returns the value of attribute branch.
-
#branch_schema ⇒ Object
readonly
Returns the value of attribute branch_schema.
Class Method Summary collapse
Instance Method Summary collapse
- #activate(shadow) ⇒ Object
- #diff ⇒ Object
- #discard(branch_name = @branch) ⇒ Object
-
#initialize(connection, config) ⇒ BranchManager
constructor
A new instance of BranchManager.
- #list ⇒ Object
- #primary_branch? ⇒ Boolean
- #prune(keep: nil) ⇒ Object
- #reset ⇒ Object
Constructor Details
#initialize(connection, config) ⇒ BranchManager
Returns a new instance of BranchManager.
8 9 10 11 12 13 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 8 def initialize(connection, config) @connection = connection @config = config @branch = resolve_branch @branch_schema = self.class.sanitise(@branch) end |
Instance Attribute Details
#branch ⇒ Object (readonly)
Returns the value of attribute branch.
6 7 8 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 6 def branch @branch end |
#branch_schema ⇒ Object (readonly)
Returns the value of attribute branch_schema.
6 7 8 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 6 def branch_schema @branch_schema end |
Class Method Details
.git_branch ⇒ Object
148 149 150 151 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 148 def self.git_branch result = `git branch --show-current 2>/dev/null`.strip result.empty? ? nil : result end |
.resolve_branch_name ⇒ Object
106 107 108 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 106 def self.resolve_branch_name ENV["PGBRANCH"] || git_branch end |
.sanitise(branch) ⇒ Object
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 72 def self.sanitise(branch) slug = branch.downcase.gsub(/[\/\-\.]/, "_").gsub(/[^a-z0-9_]/, "") schema = PREFIX + slug return schema if schema.bytesize <= MAX_SCHEMA_LENGTH hash = Digest::SHA256.hexdigest(slug)[0, 8] max_slug = MAX_SCHEMA_LENGTH - PREFIX.bytesize - 9 PREFIX + slug[0, max_slug] + "_" + hash end |
Instance Method Details
#activate(shadow) ⇒ Object
15 16 17 18 19 20 21 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 15 def activate(shadow) return if primary_branch? ensure_schema set_search_path shadow_migration_tables(shadow) end |
#diff ⇒ Object
58 59 60 61 62 63 64 65 66 67 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 58 def diff return [] if primary_branch? @connection.select_values(<<~SQL) SELECT table_name FROM information_schema.tables WHERE table_schema = #{@connection.quote(@branch_schema)} AND table_type = 'BASE TABLE' ORDER BY table_name SQL end |
#discard(branch_name = @branch) ⇒ Object
33 34 35 36 37 38 39 40 41 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 33 def discard(branch_name = @branch) schema = self.class.sanitise(branch_name) if schema == self.class.sanitise(primary_branch_name) raise "Cannot discard the primary branch schema" end @connection.execute("DROP SCHEMA IF EXISTS #{quote(schema)} CASCADE") end |
#list ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 43 def list @connection.select_rows(<<~SQL) SELECT s.schema_name, COALESCE(pg_size_pretty(sum(pg_total_relation_size( quote_ident(t.table_schema) || '.' || quote_ident(t.table_name) ))), '0 bytes') AS size FROM information_schema.schemata s LEFT JOIN information_schema.tables t ON t.table_schema = s.schema_name AND t.table_type = 'BASE TABLE' WHERE s.schema_name LIKE 'branch_%' GROUP BY s.schema_name ORDER BY s.schema_name SQL end |
#primary_branch? ⇒ Boolean
23 24 25 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 23 def primary_branch? @branch == primary_branch_name end |
#prune(keep: nil) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 83 def prune(keep: nil) keep_schemas = if keep Array(keep).map { |b| self.class.sanitise(b) }.to_set else git_branches = `git branch --list 2>/dev/null`.lines.map { |l| l.strip.delete_prefix("* ") } if git_branches.empty? raise "No git branches found. Pass branch names explicitly: prune(keep: ['main', 'feature/x'])" end git_branches.map { |b| self.class.sanitise(b) }.to_set end all_branch_schemas = @connection.select_values(<<~SQL) SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE 'branch_%' SQL stale = all_branch_schemas.reject { |s| keep_schemas.include?(s) } stale.each do |schema| @connection.execute("DROP SCHEMA IF EXISTS #{quote(schema)} CASCADE") end stale end |
#reset ⇒ Object
27 28 29 30 31 |
# File 'lib/active_record/connection_adapters/postgresql/branched/branch_manager.rb', line 27 def reset drop_schema ensure_schema set_search_path end |