diff --git a/src/charm.py b/src/charm.py index 11164fb6..2f6172b8 100755 --- a/src/charm.py +++ b/src/charm.py @@ -534,20 +534,24 @@ def _execute_migrations(self) -> None: if not self._are_relations_ready() or not container.can_connect(): logger.info("Not ready to execute migrations") return - if self.model.unit.is_leader(): - env_settings = self._create_discourse_environment_settings() - self.model.unit.status = MaintenanceStatus("Executing migrations") - try: - migration_process: ExecProcess = container.exec( - [f"{DISCOURSE_PATH}/bin/bundle", "exec", "rake", "--trace", "db:migrate"], - environment=env_settings, - working_dir=DISCOURSE_PATH, - user=CONTAINER_APP_USERNAME, - ) - migration_process.wait_output() - except ExecError as cmd_err: - logger.exception("Executing migrations failed with code %d.", cmd_err.exit_code) - raise + env_settings = self._create_discourse_environment_settings() + self.model.unit.status = MaintenanceStatus("Executing migrations") + # The rails migration task is idempotent and concurrent-safe, from + # https://stackoverflow.com/questions/17815769/are-rake-dbcreate-and-rake-dbmigrate-idempotent + # and https://github.com/rails/rails/pull/22122 + # Thus it's safe to run this task on all units to + # avoid complications with how juju schedules charm upgrades + try: + migration_process: ExecProcess = container.exec( + [f"{DISCOURSE_PATH}/bin/bundle", "exec", "rake", "--trace", "db:migrate"], + environment=env_settings, + working_dir=DISCOURSE_PATH, + user=CONTAINER_APP_USERNAME, + ) + migration_process.wait_output() + except ExecError as cmd_err: + logger.exception("Executing migrations failed with code %d.", cmd_err.exit_code) + raise def _compile_assets(self) -> None: container = self.unit.get_container(CONTAINER_NAME)