Memoize ActiveContext Elasticsearch and OpenSearch clients
Description
ActiveContext built a new Elasticsearch or OpenSearch client for every search, bulk, and delete_by_query call. This MR builds one client per adapter and reuses it.
This removes work from each call:
- OpenSearch: a new client sends a
GET /check before its first request. Now the check runs once. Locally, 9 operations sent 18 requests before and 9 after. - OpenSearch on AWS: a new client looked up AWS credentials again. With instance profile or ECS credentials, this is an HTTP call to the metadata service. Now it runs once per process. Temporary credentials still refresh when they expire.
- Elasticsearch: GitLab already disables the
GET /check. The only saving is fewer Ruby objects.
If the AWS credential lookup fails, the client now raises Aws::Sigv4::Errors::MissingCredentialsError while it is built. The failed client is not cached, so the next call tries again. The error class is the same as before.
Credentials from a shared credentials file or environment variables are now read once per process. Advanced Search already works this way.
This MR does not change how connections are reused. Typhoeus already shares them across all clients in a process. Reconnecting after a backend restart is out of scope (#598875).
Related to #598876 (closed).