Skip to content

Commit

Permalink
Fix db commands acting on same databases multiple times (#237)
Browse files Browse the repository at this point in the history
Fix bug introduced with the multiple gateway support where the `db` commands, when called without the `--app` or `--slice` args (i.e. commands intended to find all databases in the app), would operate multiple times on the same databases within a slice with >1 gateway.
  • Loading branch information
timriley authored Sep 24, 2024
1 parent d778ac3 commit 0c49496
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 21 deletions.
27 changes: 16 additions & 11 deletions lib/hanami/cli/commands/app/db/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,26 +80,31 @@ def database_for_slice(slice, gateway: nil)
def all_databases # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
slices = [app] + app.slices.with_nested

slices_by_database_url = slices.each_with_object({}) { |slice, hsh|
slice_gateways_by_database_url = slices.each_with_object({}) { |slice, hsh|
db_provider_source = slice.container.providers[:db]&.source
next unless db_provider_source

db_provider_source.database_urls.values.each do |url|
db_provider_source.database_urls.each do |gateway, url|
hsh[url] ||= []
hsh[url] << slice
hsh[url] << {slice: slice, gateway: gateway}
end
}

slices_by_database_url.each_with_object([]) { |(_url, slices_for_url), arr|
slices_with_config = slices_for_url.select { _1.root.join("config", "db").directory? }
slice_gateways_by_database_url.each_with_object([]) { |(url, slice_gateways), arr|
slice_gateways_with_config = slice_gateways.select {
_1[:slice].root.join("config", "db").directory?
}

databases = build_databases(slices_with_config.first || slices_for_url.first).values
db_slice_gateway = slice_gateways_with_config.first || slice_gateways.first
database = Utils::Database.database_class(url).new(
slice: db_slice_gateway.fetch(:slice),
gateway_name: db_slice_gateway.fetch(:gateway),
system_call: system_call
)

databases.each do |database|
warn_on_misconfigured_database database, slices_with_config
end
warn_on_misconfigured_database database, slice_gateways.map { _1.fetch(:slice) }

arr.concat databases
arr << database
}
end

Expand All @@ -124,7 +129,7 @@ def warn_on_misconfigured_database(database, slices) # rubocop:disable Metrics/A
Migrating database using #{database.slice.slice_name.to_s.inspect} slice only.
STR
elsif slices.length < 1
elsif !database.db_config_dir?
relative_path = database.slice.root
.relative_path_from(database.slice.app.root)
.join("config", "db").to_s
Expand Down
26 changes: 16 additions & 10 deletions lib/hanami/cli/commands/app/db/utils/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,17 @@ class Database
}
).freeze

def self.database_class(database_url)
database_scheme = URI(database_url).scheme
DATABASE_CLASS_RESOLVER[database_scheme].call
end

def self.from_slice(slice:, system_call:)
provider = slice.container.providers[:db]
raise "No :db provider for #{slice}" unless provider

provider.source.database_urls.map { |(gateway_name, database_url)|
database_scheme = URI(database_url).scheme
database_class = DATABASE_CLASS_RESOLVER[database_scheme].call

database = database_class.new(
database = database_class(database_url).new(
slice: slice,
gateway_name: gateway_name,
system_call: system_call
Expand Down Expand Up @@ -135,16 +137,20 @@ def applied_migrations
sequel_migrator.applied_migrations
end

def migrations_path
path = slice.root.join("config", "db")
def db_config_path
slice.root.join("config", "db")
end

def db_config_dir?
db_config_path.directory?
end

def migrations_path
if gateway_name == :default
path = path.join("migrate")
db_config_path.join("migrate")
else
path = path.join("#{gateway_name}_migrate")
db_config_path.join("#{gateway_name}_migrate")
end

path
end

def migrations_dir?
Expand Down
32 changes: 32 additions & 0 deletions spec/unit/hanami/cli/commands/app/db/drop_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,38 @@ def before_prepare
expect(command).to have_received(:exit).with(1).once
end

context "app and slice with gateways" do
def before_prepare
write "config/db/.keep", ""
write "slices/main/config/db/.keep", ""

ENV["DATABASE_URL__EXTRA"] = "sqlite://db/app_extra.sqlite3"
ENV["MAIN__DATABASE_URL__EXTRA"] = "sqlite://db/main_extra.sqlite3"
end

before do
command.run_command(Hanami::CLI::Commands::App::DB::Create)
out.truncate(0)
end

it "drops the databases for all gateways" do
expect { command.call }
.to change { File.exist?(@dir.join("db", "app.sqlite3")) }.to(false)
.and change { File.exist?(@dir.join("db", "app_extra.sqlite3")) }.to(false)
.and change { File.exist?(@dir.join("db", "main.sqlite3")) }.to(false)
.and change { File.exist?(@dir.join("db", "main_extra.sqlite3")) }.to(false)

expect(output.strip).to eq(<<~TEXT.strip)
=> database db/app.sqlite3 dropped
=> database db/app_extra.sqlite3 dropped
=> database db/main.sqlite3 dropped
=> database db/main_extra.sqlite3 dropped
TEXT

expect(command).not_to have_received(:exit)
end
end

context "app with gateways" do
def before_prepare
write "config/db/.keep", ""
Expand Down

0 comments on commit 0c49496

Please sign in to comment.