How to use singleton design pattern with Elasticsearch in Drupal 9

20 / Apr / 2022 by Nitin Kumar 0 comments

Singleton design pattern is really useful to use the same object over multiple calls. For third party softwares for examples like Apache Solr, elastic search, Redis, etc. it is not good practice to create the connection object again and again, rather a single object can be used multiple times. In such cases singleton design patterns can be used.

Drupal is flexible enough to integrate with lots of libraries, we are going to pick elasticsearch connector module integration with Drupal 9 as an example.

We will create a simple class which will connect with the elasticsearch server and will return the elasticsearch client object.

For elasticsearch, ElasticSearch Connector module is used.

We will create services for achieving the singleton object of elasticsearch. There are two services which we will use to get the objects, one will be a direct method and other will be an indirect method.

As per guidelines a custom module should be created. The files which are mentioned below should be created.

 

File name: module_name.services.yml

services:

  elastic_singleton.indirect_object:

    class: Drupal\elastic_singleton\ElasticInitiate

  elastic_singleton.direct_object:

    class: Drupal\elastic_singleton\ElasticSingleton

 

We will create the first service which supplies direct objects as per demand.

 

File name: src/ElasticSingleton.php

 

<?php

/**

 * @file

 * Contains ElasticSingleton singleton.

 */

namespace Drupal\module_name;

use Elasticsearch\ClientBuilder;

class ElasticSingleton {

  private static $instance = NULL;

  /**

   * Checks connectivity with ElasticSearch.

   */

  private static function getClient() {

    try {

      $elastic_host = ‘127.0.0.1’; // Elasticsearch server.

      $client = ClientBuilder::create()

        ->setHosts([$elastic_host])

        ->build();

      $health = $client->cluster()->health();

      if (empty($health)) {

        return FALSE;

      }

      return $client;

    }

    catch (\Exception $e) {

      return FALSE;

    }

  }

 

  /**ElasticSingleton.phpElasticSingleton.php

   * Check connectivity getInstance.

   */

  public static function getInstance() {

    if(self::$instance === NULL) {

      self::$instance = self::getClient();

    }

    return self::$instance;

  }

}

 

Now we will create a second service which will supply the same object but indirectly or using without static property/without using scope resolution operator.

 

<?php

/**

 * @file

 * Provides indirect object of elasticsearch.

 */

namespace Drupal\elastic_singleton;

use Drupal\elastic_singleton\ElasticSingleton;

class ElasticInitiate {

  /**

   * Checks connectivity with ElasticSearch.

   */

  public function getInstance() {

    return ElasticSingleton::getInstance();

  }

}

 

 

For testing we can create an entry in the routing.yml file.

File: modulename.routing.yml

elastic.test_singleton:

  path: ‘/test/elastic/singleton’

  defaults:

    _controller: ‘\Drupal\elastic_singleton\Controller\ElasticController::test’

  requirements:

    _permission: ‘access content’

 

 

Let’s create a controller in the src/Controller folder.

File Name: ElasticController.php

<?php

namespace Drupal\elastic_singleton\Controller;

use Drupal\Core\Controller\ControllerBase;

/**

 * An Elasticsearch singleton testing controller.

 */

class ElasticController extends ControllerBase {

  /**

   * Returns a render-able array for a test page.

   */

  public function test() {

    $client = \Drupal::service(‘elastic_singleton.direct_object’)::getInstance();

    var_dump($client);

    $client1 = \Drupal::service(‘elastic_singleton.indirect_object’)->getInstance();

    var_dump($client);

    // exit(); // Uncomment this line to check both the client objects.

    $build = [

      ‘#markup’ => $this->t(‘Elasticsearch Singleton example.’),

    ];

    return $build;

  }

}

 

We can call the service at desired places and we can notice that the same object is returned multiple times.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *