diff --git a/app/controllers/admin/database_diagnostics_controller.rb b/app/controllers/admin/database_diagnostics_controller.rb index d7460f35f4dca7099173153904d55e9928b39f74..d0feea6dc24203a330142cc1cd74958d796a088f 100644 --- a/app/controllers/admin/database_diagnostics_controller.rb +++ b/app/controllers/admin/database_diagnostics_controller.rb @@ -3,20 +3,56 @@ module Admin class DatabaseDiagnosticsController < Admin::ApplicationController feature_category :database - authorize! :read_admin_database_diagnostics, only: %i[index run_collation_check collation_check_results] + authorize! :read_admin_database_diagnostics, + only: %i[index run_collation_check collation_check_results run_schema_check schema_check_results] + + WORKER_CONFIGS = { + collation: { + worker: ::Database::CollationCheckerWorker, + cache_key: ::Database::CollationCheckerWorker::COLLATION_CHECK_CACHE_KEY + }, + schema: { + worker: ::Database::SchemaCheckerWorker, + cache_key: ::Database::SchemaCheckerWorker::SCHEMA_CHECK_CACHE_KEY + } + }.freeze def index # Just render the view end def run_collation_check - job_id = ::Database::CollationCheckerWorker.perform_async # rubocop:disable CodeReuse/Worker -- Simple direct call + run_check(:collation) + end - render json: { status: 'scheduled', job_id: job_id } + def run_schema_check + run_check(:schema) end def collation_check_results - results_json = Rails.cache.read(::Database::CollationCheckerWorker::COLLATION_CHECK_CACHE_KEY) + check_results(:collation) + end + + def schema_check_results + check_results(:schema) + end + + private + + def run_check(check_type) + worker_class = WORKER_CONFIGS[check_type][:worker] + job_id = worker_class.perform_async + + if job_id + render json: { status: 'scheduled', job_id: job_id } + else + render json: { error: 'Failed to schedule job' }, status: :internal_server_error + end + end + + def check_results(check_type) + cache_key = WORKER_CONFIGS[check_type][:cache_key] + results_json = Rails.cache.read(cache_key) if results_json.present? results = Gitlab::Json.parse(results_json) diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 81e89b008b81ac6450985371beac6bdde221b6c9..a810279dfc664ebc596dced1b534b3ae751b898f 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -124,6 +124,8 @@ collection do post :run_collation_check get :collation_check_results + post :run_schema_check + get :schema_check_results end end diff --git a/spec/requests/admin/database_diagnostics_controller_spec.rb b/spec/requests/admin/database_diagnostics_controller_spec.rb index 871c4bdf2f4ce894a1dd5b71e58781bcd19e56c5..dbba9dbf90b57c72d3d57e251661487f2bf01d06 100644 --- a/spec/requests/admin/database_diagnostics_controller_spec.rb +++ b/spec/requests/admin/database_diagnostics_controller_spec.rb @@ -74,6 +74,46 @@ expect(response).to have_gitlab_http_status(:ok) expect(json_response).to include('status' => 'scheduled', 'job_id' => 'job_id') end + + it 'returns 500 response when worker fails to schedule' do + expect(::Database::CollationCheckerWorker).to receive(:perform_async).and_return(nil) + + send_request + + expect(response).to have_gitlab_http_status(:internal_server_error) + expect(json_response).to include('error' => 'Failed to schedule job') + end + end + end + + describe 'POST /admin/database_diagnostics/run_schema_check' do + subject(:send_request) do + post run_schema_check_admin_database_diagnostics_path(format: :json) + end + + it_behaves_like 'unauthorized request' + + context 'when admin mode is enabled', :enable_admin_mode do + before do + login_as(admin) + end + + it 'returns 200 response and schedules the worker' do + expect(::Database::SchemaCheckerWorker).to receive(:perform_async).and_return('schema_job_id') + + send_request + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to include('status' => 'scheduled', 'job_id' => 'schema_job_id') + end + + it 'returns 500 response when worker fails to schedule' do + expect(::Database::SchemaCheckerWorker).to receive(:perform_async).and_return(nil) + + send_request + + expect(response).to have_gitlab_http_status(:internal_server_error) + expect(json_response).to include('error' => 'Failed to schedule job') + end end end @@ -125,4 +165,52 @@ end end end + + describe 'GET /admin/database_diagnostics/schema_check_results' do + subject(:send_request) do + get schema_check_results_admin_database_diagnostics_path(format: :json) + end + + it_behaves_like 'unauthorized request' + + context 'when admin mode is enabled', :enable_admin_mode do + before do + login_as(admin) + end + + context 'when results are available' do + let(:results) do + { + metadata: { last_run_at: Time.current.iso8601 }, + schema_check_results: { + main: { + missing_indexes: [] + } + } + } + end + + it 'returns 200 response with the results' do + allow(Rails.cache).to receive(:read) + expect(Rails.cache).to receive(:read) + .with(::Database::SchemaCheckerWorker::SCHEMA_CHECK_CACHE_KEY) + .and_return(results.to_json) + + send_request + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to include('schema_check_results', 'metadata') + end + end + + context 'when no results are available' do + it 'returns 404 response' do + send_request + + expect(response).to have_gitlab_http_status(:not_found) + expect(json_response).to include('error' => 'No results available yet') + end + end + end + end end