From 347f28a3119fab6116c0963e67fbe810bda3d498 Mon Sep 17 00:00:00 2001 From: Dave Arter Date: Wed, 25 Sep 2024 13:53:45 +0100 Subject: [PATCH] Add healthcheck page at /status/health --- CHANGELOG.md | 1 + perllib/FixMyStreet/App/Controller/Status.pm | 27 ++++++++++++++++++- t/app/controller/status.t | 28 ++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 t/app/controller/status.t diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b2dc9e4b7..aa942aaa6fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ - Add perl 5.38 support. - Add plain text template previews to /_dev/email. #5105 - Add --exclude option to bin/open311-populate-service-list + - Add /status/health page to indicate service health. - Performance improvements: - Reduce database queries on shortlist page. - Provide ResultSet fallback translation in lookup. diff --git a/perllib/FixMyStreet/App/Controller/Status.pm b/perllib/FixMyStreet/App/Controller/Status.pm index e56a7930a75..db91d65fd86 100755 --- a/perllib/FixMyStreet/App/Controller/Status.pm +++ b/perllib/FixMyStreet/App/Controller/Status.pm @@ -4,6 +4,7 @@ use namespace::autoclean; use HTTP::Negotiate; use JSON::MaybeXS; +use Try::Tiny; BEGIN { extends 'Catalyst::Controller'; } @@ -46,7 +47,6 @@ sub index : Path : Args(0) { $chosen = 'html' unless $chosen; } - # TODO Perform health checks here if ($chosen eq 'json') { $c->res->content_type('application/json; charset=utf-8'); @@ -68,6 +68,31 @@ sub index : Path : Args(0) { return 1; } +sub health : Path('health') : Args(0) { + my ($self, $c) = @_; + + # Just do a very simple and inexpensive query to confirm DB connectivity + my $id = try { + $c->model('DB::Problem')->search(undef, { + columns => [ "id" ], + rows => 1, + order_by => { -desc => 'id' }, + })->first->id; + } catch { + undef; + }; + + $c->res->content_type('text/plain; charset=utf-8'); + $c->res->headers->header('Cache-Control' => 'max-age=0'); + if ($id) { + $c->res->body("OK: $id"); + } else { + $c->response->status("500"); + $c->res->body("ERROR: Couldn't get last problem ID from DB"); + } +} + + __PACKAGE__->meta->make_immutable; 1; diff --git a/t/app/controller/status.t b/t/app/controller/status.t new file mode 100644 index 00000000000..c8c1766ec36 --- /dev/null +++ b/t/app/controller/status.t @@ -0,0 +1,28 @@ +use FixMyStreet::TestMech; +use Test::MockModule; + + +ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' ); + +my $surrey = $mech->create_body_ok(2242, 'Surrey County Council'); +(my $report) = $mech->create_problems_for_body(1, $surrey->id, 'Pothole', { + category => 'Potholes', cobrand => 'surrey', + latitude => 51.293415, longitude => -0.441269, areas => '2242', +}); + + +subtest 'Health page returns 200 when things are OK' => sub { + $mech->get_ok('/status/health'); + is $mech->content, 'OK: ' . $report->id, 'Got correct content for status page'; + is $mech->res->code, 200, 'Got 200 for status page'; +}; + +subtest 'Health page returns 500 when things are not OK' => sub { + my $rs = Test::MockModule->new('FixMyStreet::DB::ResultSet::Problem'); + $rs->mock('first', sub { die 'DB error' }); + $mech->get('/status/health'); + is $mech->res->code, 500, 'Got 500 for status page'; +}; + + +done_testing();