1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: Apache-2.0
4 """Thread-safe wrapper for an Arvados API client
6 This module provides `ThreadSafeApiCache`, a thread-safe, API-compatible
10 from __future__ import absolute_import
12 from builtins import object
20 class ThreadSafeApiCache(object):
21 """Thread-safe wrapper for an Arvados API client
23 This class takes all the arguments necessary to build a lower-level
24 Arvados API client `googleapiclient.discovery.Resource`, then
25 transparently builds and wraps a unique object per thread. This works
26 around the fact that the client's underlying HTTP client object is not
31 apiconfig: Mapping[str, str] | None
32 : A mapping with entries for `ARVADOS_API_HOST`, `ARVADOS_API_TOKEN`,
33 and optionally `ARVADOS_API_HOST_INSECURE`. If not provided, uses
34 `arvados.config.settings` to get these parameters from user
35 configuration. You can pass an empty mapping to build the client
36 solely from `api_params`.
38 keep_params: Mapping[str, Any]
39 : Keyword arguments used to construct an associated
40 `arvados.keep.KeepClient`.
42 api_params: Mapping[str, Any]
43 : Keyword arguments used to construct each thread's API client. These
44 have the same meaning as in the `arvados.api.api` function.
47 : A string naming the version of the Arvados API to use. If not specified,
48 the code will log a warning and fall back to 'v1'.
51 def __init__(self, apiconfig=None, keep_params={}, api_params={}, version=None):
52 if apiconfig or apiconfig is None:
53 self._api_kwargs = api.api_kwargs_from_config(version, apiconfig, **api_params)
55 self._api_kwargs = api.normalize_api_kwargs(version, **api_params)
56 self.api_token = self._api_kwargs['token']
57 self.request_id = self._api_kwargs.get('request_id')
58 self.local = threading.local()
59 self.keep = keep.KeepClient(api_client=self, **keep_params)
63 client = self.local.api
64 except AttributeError:
65 client = api.api_client(**self._api_kwargs)
66 client._http._request_id = lambda: self.request_id or util.new_request_id()
67 self.local.api = client
70 def __getattr__(self, name):
71 # Proxy nonexistent attributes to the thread-local API client.
72 return getattr(self.localapi(), name)