From 5ccc298290a7914d07115ef16bafc1cbe0095001 Mon Sep 17 00:00:00 2001 From: Kalle Vuorjoki <21761-kallevu@users.noreply.drupalcode.org> Date: Fri, 20 Sep 2024 05:59:13 +0000 Subject: [PATCH] Issue #3187670 by sokru, man-1982: entity.search_api_index.canonical route will produce fatal error when backend is down --- src/SearchAPI/BackendClient.php | 20 +++-- ...rch_api.index.test_elasticsearch_index.yml | 2 +- ...search_api.server.elasticsearch_server.yml | 2 +- .../elasticsearch_connector_test.info.yml | 4 +- .../ElasticsearchConnectorBackendTest.php | 86 +++++++++++++++++++ 5 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 tests/src/Functional/ElasticsearchConnectorBackendTest.php diff --git a/src/SearchAPI/BackendClient.php b/src/SearchAPI/BackendClient.php index b8fdf7873..aecc9c1aa 100644 --- a/src/SearchAPI/BackendClient.php +++ b/src/SearchAPI/BackendClient.php @@ -34,6 +34,8 @@ class BackendClient implements BackendClientInterface { * {@inheritdoc} */ public function isAvailable() { + // @todo If https://github.com/elastic/elasticsearch-php/issues/1308 gets + // fixed, we could provide more information about the error. try { $this->client->ping(); return TRUE; @@ -42,6 +44,10 @@ class BackendClient implements BackendClientInterface { $this->logger->error('%type: @message in %function (line %line of %file).', Error::decodeException($e)); return FALSE; } + catch (\Exception $e) { + $this->logger->error('%type: @message in %function (line %line of %file).', Error::decodeException($e)); + return FALSE; + } } /** @@ -149,11 +155,15 @@ class BackendClient implements BackendClientInterface { $params = [ 'index' => $indexId, ]; - - // Check index exists. - if (!$this->client->indices()->exists($params)) { - $this->logger->warning('Index "%index" does not exist.', ["%index" => $indexId]); - return $resultSet; + try { + // Check index exists. + if (!$this->client->indices()->exists($params)) { + $this->logger->warning('Index "%index" does not exist.', ["%index" => $indexId]); + return $resultSet; + } + } + catch (\Exception $e) { + throw new SearchApiException(sprintf('Error: %s', $e->getMessage()), 0, $e); } // Build ElasticSearch query. diff --git a/tests/modules/elasticsearch_connector_test/config/install/search_api.index.test_elasticsearch_index.yml b/tests/modules/elasticsearch_connector_test/config/install/search_api.index.test_elasticsearch_index.yml index 229628a4e..dddc078c6 100644 --- a/tests/modules/elasticsearch_connector_test/config/install/search_api.index.test_elasticsearch_index.yml +++ b/tests/modules/elasticsearch_connector_test/config/install/search_api.index.test_elasticsearch_index.yml @@ -68,7 +68,7 @@ field_settings: datasource_id: 'entity:entity_test_mulrev_changed' property_path: name type: text - boost: !!float 5 + boost: 5.0 dependencies: module: - entity_test diff --git a/tests/modules/elasticsearch_connector_test/config/install/search_api.server.elasticsearch_server.yml b/tests/modules/elasticsearch_connector_test/config/install/search_api.server.elasticsearch_server.yml index 318b14d09..4aee9c213 100644 --- a/tests/modules/elasticsearch_connector_test/config/install/search_api.server.elasticsearch_server.yml +++ b/tests/modules/elasticsearch_connector_test/config/install/search_api.server.elasticsearch_server.yml @@ -2,7 +2,7 @@ langcode: en status: true dependencies: module: - - elasticsearch + - elasticsearch_connector id: elasticsearch_server name: elasticsearch_server description: 'Local test server' diff --git a/tests/modules/elasticsearch_connector_test/elasticsearch_connector_test.info.yml b/tests/modules/elasticsearch_connector_test/elasticsearch_connector_test.info.yml index d8ae76379..899928920 100644 --- a/tests/modules/elasticsearch_connector_test/elasticsearch_connector_test.info.yml +++ b/tests/modules/elasticsearch_connector_test/elasticsearch_connector_test.info.yml @@ -3,6 +3,8 @@ name: 'ElasticSearch Connector Test' description: 'ElasticSearch Connector test module' package: 'Search' dependencies: - - drupal:search_api_test + - elasticsearch_connector:elasticsearch_connector + - search_api:search_api_test + - search_api:search_api_test_example_content core_version_requirement: ^9 || ^10 | ^11 hidden: true diff --git a/tests/src/Functional/ElasticsearchConnectorBackendTest.php b/tests/src/Functional/ElasticsearchConnectorBackendTest.php new file mode 100644 index 000000000..5d922f867 --- /dev/null +++ b/tests/src/Functional/ElasticsearchConnectorBackendTest.php @@ -0,0 +1,86 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\elasticsearch_connector\Functional; + +use Drupal\Core\Url; +use Drupal\Tests\BrowserTestBase; + +/** + * Tests for situations when backend is down. + * + * @group elasticsearch_connector + */ +class ElasticsearchConnectorBackendTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'dblog', + 'elasticsearch_connector', + 'elasticsearch_connector_test', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + // Create an admin user. + $admin_user = $this->drupalCreateUser([ + 'access administration pages', + 'access site reports', + 'administer search_api', + ]); + $this->drupalLogin($admin_user); + } + + /** + * Tests that no exception is thrown when visiting the Search API routes. + */ + public function testSearchApiRoutes() { + $assert_session = $this->assertSession(); + + // Alter the Elasticsearch server configuration to cause failure to connect + // to Elasticsearch server. + $config = $this->config('search_api.server.elasticsearch_server'); + $config->set('backend_config.connector_config.url', 'http://elasticsearch:9999'); + $config->save(); + + // Assert "search_api.overview" route loads without errors. + $url = Url::fromRoute('search_api.overview'); + $this->drupalGet($url); + $this->assertSession()->statusCodeEquals(200); + $assert_session->elementTextContains('css', '.search-api-server-elasticsearch-server .search-api-status', 'Unavailable'); + + // Assert "entity.search_api_server.canonical" route loads without errors. + $url = Url::fromRoute('entity.search_api_server.canonical', [ + 'search_api_server' => 'elasticsearch_server', + ]); + $this->drupalGet($url); + $this->assertSession()->statusCodeEquals(200); + $assert_session->pageTextContains('Local test server'); + + // Assert "entity.search_api_index.canonical" route loads without errors. + $url = Url::fromRoute('entity.search_api_index.canonical', [ + 'search_api_index' => 'test_elasticsearch_index', + ]); + $this->drupalGet($url); + $assert_session->statusCodeEquals(200); + $assert_session->pageTextContains('Test Index'); + $assert_session->elementTextContains('css', '.search-api-index-summary--server-index-status', 'Error while checking server index status'); + + // Assert error produced on "search_api.overview" route is logged. + $this->drupalGet('/admin/reports/dblog'); + $assert_session->pageTextContains('Elastic\Transport\Exception\NoNodeAvailableException'); + } + +} -- GitLab