Files
grecia/lib/tasks/db.rake
Javi Martín c483c6036a Install extensions in a shared schema
This way all tenants will be able to access them instead of just the
default one.

The apartment gem recommends using a rake task instead of a migration,
but that's a solution which is primarily meant for new installations.
Migrations are easier to execute on existing installations.

However, since this migration doesn't affect the `schema.rb` file, we
still need to make sure the shared schema is created in tasks which do
not execute migrations, like `db:schema:load` or `db:test:prepare`, just
like the apartment gem recommends. That's why we're enhancing these
tasks so they execute this migration.

Note that there might be cases where the database user isn't a superuser
(as it's usually the case on production environments), meaning commands
to create, alter or drop extensions will fail. There's also the case
where users don't have permissions to create schemas, which is needed in
order to create the shared extensions schema and the schemas used by the
tenants. For these reasons, we're minimizing the number of commands, and
so we only alter or create extensions when it is really necessary.

When users don't have permission, we aren't running the commands but
showing a warning with the steps needed to run the migration manually.
This is only necessary on installations which are going to use
multitenancy; single-tenant applications upgrading don't need to run
this migration, and that's why we aren't raising exceptions when we
can't run it.

For new installations, we'll change the CONSUL installer so extensions
are automatically created in the shared schema.

Also note the plpgsql extension is not handled here. This is a special
extension which must be installed on the pg_catalog schema, which is
always in the search path and so is shared by all tenants.

Finally, we also need to change the `database.yml` file in order to
search for shared extensions while running migrations or model tests,
since none of our enabled extensions are executed during migrations;
we're also adding a rake task for existing installations. Quoting the
apartment documentation:

> your database.yml file must mimic what you've set for your default and
> persistent schemas in Apartment. When you run migrations with Rails,
> it won't know about the extensions schema because Apartment isn't
> injected into the default connection, it's done on a per-request
> basis.
2022-11-09 17:53:31 +01:00

46 lines
1.6 KiB
Ruby

namespace :db do
desc "Resets the database and loads it from db/dev_seeds.rb"
task :dev_seed, [:print_log] => [:environment] do |t, args|
@avoid_log = args[:print_log] == "avoid_log"
I18n.enforce_available_locales = false
load(Rails.root.join("db", "dev_seeds.rb"))
end
desc "Calculates the TSV column for all comments and proposal notifications"
task calculate_tsv: :environment do
logger = ApplicationLogger.new
logger.info "Calculating tsvector for comments"
Comment.with_hidden.find_each(&:calculate_tsvector)
logger.info "Calculating tsvector for proposal notifications"
ProposalNotification.with_hidden.find_each(&:calculate_tsvector)
end
desc "Adds shared extensions to the schema search path in the database.yml file"
task add_schema_search_path: :environment do
logger = ApplicationLogger.new
logger.info "Adding search path to config/database.yml"
config = Rails.application.config.paths["config/database"].first
lines = File.readlines(config)
changes_done = false
adapter_indices = lines.map.with_index do |line, index|
index if line.start_with?(" adapter: postgresql")
end.compact
adapter_indices.reverse_each do |index|
unless lines[index + 1]&.match?("schema_search_path")
lines.insert(index + 1, " schema_search_path: \"public,shared_extensions\"\n")
changes_done = true
end
end
if changes_done
File.write(config, lines.join)
logger.warn "The database search path has been updated. Restart the application to apply the changes."
end
end
end