ffbb-data-client 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ffbb_api_client_v3/__init__.py +25 -0
- ffbb_data_client/__init__.py +175 -0
- ffbb_data_client/clients/__init__.py +13 -0
- ffbb_data_client/clients/api_ffbb_app_client.py +2475 -0
- ffbb_data_client/clients/ffbb_data_client.py +2789 -0
- ffbb_data_client/clients/meilisearch_client.py +218 -0
- ffbb_data_client/clients/meilisearch_ffbb_client.py +647 -0
- ffbb_data_client/config.py +153 -0
- ffbb_data_client/data/__init__.py +25 -0
- ffbb_data_client/data/collections.json +1364 -0
- ffbb_data_client/data/endpoint_discovery.json +1875 -0
- ffbb_data_client/data/indexes.json +501 -0
- ffbb_data_client/data/openapi.json +35713 -0
- ffbb_data_client/data/openapi_full.json +37622 -0
- ffbb_data_client/helpers/__init__.py +27 -0
- ffbb_data_client/helpers/http_requests_helper.py +73 -0
- ffbb_data_client/helpers/http_requests_utils.py +502 -0
- ffbb_data_client/helpers/meilisearch_client_extension.py +153 -0
- ffbb_data_client/helpers/multi_search_query_helper.py +35 -0
- ffbb_data_client/models/__init__.py +241 -0
- ffbb_data_client/models/affiche.py +45 -0
- ffbb_data_client/models/cartographie.py +82 -0
- ffbb_data_client/models/categorie.py +55 -0
- ffbb_data_client/models/categorie_type.py +42 -0
- ffbb_data_client/models/clock.py +38 -0
- ffbb_data_client/models/club_contacts.py +77 -0
- ffbb_data_client/models/code.py +7 -0
- ffbb_data_client/models/commune.py +66 -0
- ffbb_data_client/models/competition_fields.py +309 -0
- ffbb_data_client/models/competition_id.py +116 -0
- ffbb_data_client/models/competition_id_categorie.py +31 -0
- ffbb_data_client/models/competition_id_sexe.py +31 -0
- ffbb_data_client/models/competition_id_type_competition.py +27 -0
- ffbb_data_client/models/competition_id_type_competition_generique.py +24 -0
- ffbb_data_client/models/competition_origine.py +69 -0
- ffbb_data_client/models/competition_origine_categorie.py +23 -0
- ffbb_data_client/models/competition_origine_type_competition.py +14 -0
- ffbb_data_client/models/competition_origine_type_competition_generique.py +24 -0
- ffbb_data_client/models/competition_type.py +6 -0
- ffbb_data_client/models/competitions_facet_distribution.py +65 -0
- ffbb_data_client/models/competitions_facet_stats.py +14 -0
- ffbb_data_client/models/competitions_hit.py +232 -0
- ffbb_data_client/models/competitions_multi_search_query.py +40 -0
- ffbb_data_client/models/competitions_query.py +11 -0
- ffbb_data_client/models/configuration_models.py +5 -0
- ffbb_data_client/models/contact_info.py +18 -0
- ffbb_data_client/models/content_multi_search_query.py +93 -0
- ffbb_data_client/models/coordonnees.py +27 -0
- ffbb_data_client/models/coordonnees_type.py +5 -0
- ffbb_data_client/models/document_flyer.py +205 -0
- ffbb_data_client/models/document_flyer_type.py +6 -0
- ffbb_data_client/models/engagement_contacts.py +97 -0
- ffbb_data_client/models/engagements_facet_distribution.py +59 -0
- ffbb_data_client/models/engagements_facet_stats.py +14 -0
- ffbb_data_client/models/engagements_hit.py +192 -0
- ffbb_data_client/models/engagements_multi_search_query.py +41 -0
- ffbb_data_client/models/etat.py +6 -0
- ffbb_data_client/models/external_competition_id.py +42 -0
- ffbb_data_client/models/external_id.py +72 -0
- ffbb_data_client/models/facet_distribution.py +13 -0
- ffbb_data_client/models/facet_stats.py +13 -0
- ffbb_data_client/models/field_set.py +10 -0
- ffbb_data_client/models/folder.py +35 -0
- ffbb_data_client/models/formation_session.py +60 -0
- ffbb_data_client/models/formations_facet_distribution.py +61 -0
- ffbb_data_client/models/formations_facet_stats.py +14 -0
- ffbb_data_client/models/formations_hit.py +277 -0
- ffbb_data_client/models/formations_multi_search_query.py +41 -0
- ffbb_data_client/models/game_stats_model.py +57 -0
- ffbb_data_client/models/game_stats_models.py +5 -0
- ffbb_data_client/models/generic_search.py +92 -0
- ffbb_data_client/models/geo.py +27 -0
- ffbb_data_client/models/geo_sort_order.py +6 -0
- ffbb_data_client/models/get_commune_response.py +18 -0
- ffbb_data_client/models/get_competition_response.py +523 -0
- ffbb_data_client/models/get_configuration_response.py +45 -0
- ffbb_data_client/models/get_engagement_response.py +23 -0
- ffbb_data_client/models/get_entraineur_response.py +18 -0
- ffbb_data_client/models/get_formation_response.py +28 -0
- ffbb_data_client/models/get_officiel_response.py +18 -0
- ffbb_data_client/models/get_organisme_response.py +476 -0
- ffbb_data_client/models/get_poule_response.py +68 -0
- ffbb_data_client/models/get_pratique_response.py +18 -0
- ffbb_data_client/models/get_rencontre_response.py +93 -0
- ffbb_data_client/models/get_saisons_response.py +56 -0
- ffbb_data_client/models/get_salle_response.py +20 -0
- ffbb_data_client/models/get_terrain_response.py +16 -0
- ffbb_data_client/models/get_tournoi_response.py +16 -0
- ffbb_data_client/models/gradient_color.py +27 -0
- ffbb_data_client/models/hit.py +16 -0
- ffbb_data_client/models/id_engagement_equipe.py +32 -0
- ffbb_data_client/models/id_organisme_equipe.py +51 -0
- ffbb_data_client/models/id_organisme_equipe1_logo.py +28 -0
- ffbb_data_client/models/id_poule.py +27 -0
- ffbb_data_client/models/jour.py +11 -0
- ffbb_data_client/models/label.py +15 -0
- ffbb_data_client/models/labellisation.py +30 -0
- ffbb_data_client/models/live.py +192 -0
- ffbb_data_client/models/lives.py +6 -0
- ffbb_data_client/models/logo.py +28 -0
- ffbb_data_client/models/multi_search_queries.py +24 -0
- ffbb_data_client/models/multi_search_query.py +96 -0
- ffbb_data_client/models/multi_search_result_competitions.py +14 -0
- ffbb_data_client/models/multi_search_result_engagements.py +14 -0
- ffbb_data_client/models/multi_search_result_formations.py +12 -0
- ffbb_data_client/models/multi_search_result_organismes.py +12 -0
- ffbb_data_client/models/multi_search_result_pratiques.py +12 -0
- ffbb_data_client/models/multi_search_result_rencontres.py +12 -0
- ffbb_data_client/models/multi_search_result_salles.py +12 -0
- ffbb_data_client/models/multi_search_result_terrains.py +12 -0
- ffbb_data_client/models/multi_search_result_tournois.py +12 -0
- ffbb_data_client/models/multi_search_results.py +103 -0
- ffbb_data_client/models/multi_search_results_class.py +96 -0
- ffbb_data_client/models/nature_sol.py +57 -0
- ffbb_data_client/models/niveau.py +10 -0
- ffbb_data_client/models/niveau_class.py +27 -0
- ffbb_data_client/models/niveau_extractor.py +214 -0
- ffbb_data_client/models/niveau_info.py +64 -0
- ffbb_data_client/models/niveau_models.py +14 -0
- ffbb_data_client/models/niveau_type.py +10 -0
- ffbb_data_client/models/objectif.py +7 -0
- ffbb_data_client/models/organisateur.py +197 -0
- ffbb_data_client/models/organisateur_type.py +6 -0
- ffbb_data_client/models/organisme_fields.py +327 -0
- ffbb_data_client/models/organisme_id_pere.py +177 -0
- ffbb_data_client/models/organismes_facet_distribution.py +46 -0
- ffbb_data_client/models/organismes_facet_stats.py +14 -0
- ffbb_data_client/models/organismes_hit.py +196 -0
- ffbb_data_client/models/organismes_multi_search_query.py +41 -0
- ffbb_data_client/models/organismes_query.py +8 -0
- ffbb_data_client/models/phase_code.py +23 -0
- ffbb_data_client/models/poule.py +35 -0
- ffbb_data_client/models/poule_fields.py +261 -0
- ffbb_data_client/models/poule_rencontre_item_model.py +69 -0
- ffbb_data_client/models/poules_models.py +6 -0
- ffbb_data_client/models/poules_query.py +9 -0
- ffbb_data_client/models/pratique.py +7 -0
- ffbb_data_client/models/pratiques_facet_distribution.py +29 -0
- ffbb_data_client/models/pratiques_facet_stats.py +14 -0
- ffbb_data_client/models/pratiques_hit.py +310 -0
- ffbb_data_client/models/pratiques_hit_type.py +9 -0
- ffbb_data_client/models/pratiques_multi_search_query.py +41 -0
- ffbb_data_client/models/pratiques_type_class.py +45 -0
- ffbb_data_client/models/publication_internet.py +6 -0
- ffbb_data_client/models/purple_logo.py +24 -0
- ffbb_data_client/models/query_fields_manager.py +75 -0
- ffbb_data_client/models/ranking_engagement.py +41 -0
- ffbb_data_client/models/rankings_models.py +6 -0
- ffbb_data_client/models/rencontres_engagement.py +23 -0
- ffbb_data_client/models/rencontres_facet_distribution.py +65 -0
- ffbb_data_client/models/rencontres_facet_stats.py +14 -0
- ffbb_data_client/models/rencontres_hit.py +271 -0
- ffbb_data_client/models/rencontres_multi_search_query.py +41 -0
- ffbb_data_client/models/saison.py +23 -0
- ffbb_data_client/models/saison_fields.py +36 -0
- ffbb_data_client/models/saisons_models.py +6 -0
- ffbb_data_client/models/saisons_query.py +9 -0
- ffbb_data_client/models/salle.py +56 -0
- ffbb_data_client/models/salles_facet_distribution.py +14 -0
- ffbb_data_client/models/salles_facet_stats.py +14 -0
- ffbb_data_client/models/salles_hit.py +153 -0
- ffbb_data_client/models/salles_multi_search_query.py +40 -0
- ffbb_data_client/models/sexe.py +9 -0
- ffbb_data_client/models/sexe_class.py +31 -0
- ffbb_data_client/models/source.py +5 -0
- ffbb_data_client/models/status.py +5 -0
- ffbb_data_client/models/team_engagement.py +56 -0
- ffbb_data_client/models/team_ranking.py +108 -0
- ffbb_data_client/models/terrains_categorie_championnat_3x3_libelle.py +5 -0
- ffbb_data_client/models/terrains_facet_distribution.py +41 -0
- ffbb_data_client/models/terrains_facet_stats.py +14 -0
- ffbb_data_client/models/terrains_hit.py +223 -0
- ffbb_data_client/models/terrains_multi_search_query.py +42 -0
- ffbb_data_client/models/terrains_name.py +5 -0
- ffbb_data_client/models/terrains_sexe_enum.py +7 -0
- ffbb_data_client/models/terrains_storage.py +5 -0
- ffbb_data_client/models/tournoi_type_class.py +35 -0
- ffbb_data_client/models/tournoi_type_enum.py +7 -0
- ffbb_data_client/models/tournoi_types_3x3.py +43 -0
- ffbb_data_client/models/tournoi_types_3x3_libelle.py +60 -0
- ffbb_data_client/models/tournoi_types_3x3_libelle_enum.py +10 -0
- ffbb_data_client/models/tournois_facet_distribution.py +41 -0
- ffbb_data_client/models/tournois_facet_stats.py +14 -0
- ffbb_data_client/models/tournois_hit.py +132 -0
- ffbb_data_client/models/tournois_hit_type.py +5 -0
- ffbb_data_client/models/tournois_libelle.py +7 -0
- ffbb_data_client/models/tournois_multi_search_query.py +40 -0
- ffbb_data_client/models/type_association.py +23 -0
- ffbb_data_client/models/type_association_libelle.py +30 -0
- ffbb_data_client/models/type_class.py +23 -0
- ffbb_data_client/models/type_competition.py +8 -0
- ffbb_data_client/models/type_competition_generique.py +31 -0
- ffbb_data_client/models/type_enum.py +7 -0
- ffbb_data_client/models/type_league.py +6 -0
- ffbb_data_client/py.typed +0 -0
- ffbb_data_client/utils/__init__.py +27 -0
- ffbb_data_client/utils/cache_manager.py +393 -0
- ffbb_data_client/utils/converter_utils.py +329 -0
- ffbb_data_client/utils/input_validation.py +360 -0
- ffbb_data_client/utils/retry_utils.py +478 -0
- ffbb_data_client/utils/secure_logging.py +153 -0
- ffbb_data_client/utils/token_manager.py +115 -0
- ffbb_data_client-2.0.0.dist-info/METADATA +339 -0
- ffbb_data_client-2.0.0.dist-info/RECORD +207 -0
- ffbb_data_client-2.0.0.dist-info/WHEEL +5 -0
- ffbb_data_client-2.0.0.dist-info/licenses/LICENSE.txt +201 -0
- ffbb_data_client-2.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
import threading
|
|
6
|
+
import time
|
|
7
|
+
from collections.abc import Sequence
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
from httpx import Client
|
|
12
|
+
|
|
13
|
+
from ..config import (
|
|
14
|
+
DEFAULT_USER_AGENT,
|
|
15
|
+
MEILISEARCH_BASE_URL,
|
|
16
|
+
MEILISEARCH_ENDPOINT_MULTI_SEARCH,
|
|
17
|
+
)
|
|
18
|
+
from ..helpers.http_requests_helper import catch_result
|
|
19
|
+
from ..helpers.http_requests_utils import (
|
|
20
|
+
http_post_json,
|
|
21
|
+
http_post_json_async,
|
|
22
|
+
)
|
|
23
|
+
from ..models.multi_search_query import MultiSearchQuery
|
|
24
|
+
from ..models.multi_search_results_class import MultiSearchResults
|
|
25
|
+
from ..utils.cache_manager import CacheManager
|
|
26
|
+
from ..utils.retry_utils import (
|
|
27
|
+
RetryConfig,
|
|
28
|
+
TimeoutConfig,
|
|
29
|
+
get_default_retry_config,
|
|
30
|
+
get_default_timeout_config,
|
|
31
|
+
)
|
|
32
|
+
from ..utils.secure_logging import get_secure_logger, mask_token
|
|
33
|
+
|
|
34
|
+
_APP_CACHE: dict[str, tuple[float, Any]] = {}
|
|
35
|
+
_APP_CACHE_LOCK = threading.Lock()
|
|
36
|
+
_APP_CACHE_TTL: int = 300 # secondes, modifiable
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _make_cache_key(queries: Sequence[MultiSearchQuery] | None) -> str:
|
|
40
|
+
payload = [q.to_dict() for q in queries] if queries else []
|
|
41
|
+
raw = json.dumps(payload, sort_keys=True, default=str)
|
|
42
|
+
return hashlib.md5(raw.encode(), usedforsecurity=False).hexdigest()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _cache_get(key: str) -> Any | None:
|
|
46
|
+
with _APP_CACHE_LOCK:
|
|
47
|
+
entry = _APP_CACHE.get(key)
|
|
48
|
+
if entry is None:
|
|
49
|
+
return None
|
|
50
|
+
ts, value = entry
|
|
51
|
+
if time.monotonic() - ts > _APP_CACHE_TTL:
|
|
52
|
+
with _APP_CACHE_LOCK:
|
|
53
|
+
_APP_CACHE.pop(key, None)
|
|
54
|
+
return None
|
|
55
|
+
return value
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _cache_set(key: str, value: Any) -> None:
|
|
59
|
+
with _APP_CACHE_LOCK:
|
|
60
|
+
_APP_CACHE[key] = (time.monotonic(), value)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _result_from_cached_payload(payload: Any) -> MultiSearchResults | None:
|
|
64
|
+
return MultiSearchResults.from_dict(payload) if isinstance(payload, dict) else None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _cache_result_payload(key: str, result: MultiSearchResults) -> None:
|
|
68
|
+
_cache_set(key, result.to_dict())
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def clear_meili_app_cache() -> None:
|
|
72
|
+
"""Vide le cache applicatif (utile pour les tests)."""
|
|
73
|
+
with _APP_CACHE_LOCK:
|
|
74
|
+
_APP_CACHE.clear()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
logger = get_secure_logger(__name__)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class MeilisearchClient:
|
|
81
|
+
url: str = ""
|
|
82
|
+
debug: bool = False
|
|
83
|
+
cached_session: Client | None = None
|
|
84
|
+
async_cached_session: httpx.AsyncClient | None = None
|
|
85
|
+
retry_config: RetryConfig | None = None
|
|
86
|
+
timeout_config: TimeoutConfig | None = None
|
|
87
|
+
|
|
88
|
+
def __init__(
|
|
89
|
+
self,
|
|
90
|
+
bearer_token: str,
|
|
91
|
+
url: str = MEILISEARCH_BASE_URL,
|
|
92
|
+
debug: bool = False,
|
|
93
|
+
cached_session: Client | None = None,
|
|
94
|
+
*,
|
|
95
|
+
async_cached_session: httpx.AsyncClient | None = None,
|
|
96
|
+
retry_config: RetryConfig | None = None,
|
|
97
|
+
timeout_config: TimeoutConfig | None = None,
|
|
98
|
+
):
|
|
99
|
+
"""
|
|
100
|
+
Initializes an instance of the MeilisearchClient class.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
bearer_token (str): The bearer token used for authentication.
|
|
104
|
+
url (str, optional): The base URL.
|
|
105
|
+
Defaults to "https://meilisearch-prod.ffbb.app/".
|
|
106
|
+
debug (bool, optional): Whether to enable debug mode. Defaults to False.
|
|
107
|
+
cached_session (Client, optional): The cached session to use.
|
|
108
|
+
retry_config (RetryConfig, optional): Retry configuration. Defaults to None.
|
|
109
|
+
timeout_config (TimeoutConfig, optional): Timeout configuration.
|
|
110
|
+
Defaults to None.
|
|
111
|
+
"""
|
|
112
|
+
if not bearer_token or not bearer_token.strip():
|
|
113
|
+
raise ValueError("bearer_token cannot be None, empty, or whitespace-only")
|
|
114
|
+
|
|
115
|
+
# Store token securely (private attribute)
|
|
116
|
+
self._bearer_token = bearer_token
|
|
117
|
+
self.url = url
|
|
118
|
+
self.debug = debug
|
|
119
|
+
self.cached_session = (
|
|
120
|
+
cached_session if cached_session else CacheManager().session
|
|
121
|
+
)
|
|
122
|
+
self.async_cached_session = (
|
|
123
|
+
async_cached_session
|
|
124
|
+
if async_cached_session
|
|
125
|
+
else CacheManager().async_session
|
|
126
|
+
)
|
|
127
|
+
self.headers = {
|
|
128
|
+
"Authorization": f"Bearer {self._bearer_token}",
|
|
129
|
+
"Content-Type": "application/json",
|
|
130
|
+
"user-agent": DEFAULT_USER_AGENT,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
# Configure retry and timeout settings
|
|
134
|
+
self.retry_config = retry_config or get_default_retry_config()
|
|
135
|
+
self.timeout_config = timeout_config or get_default_timeout_config()
|
|
136
|
+
|
|
137
|
+
# Initialize secure logger
|
|
138
|
+
self.logger = get_secure_logger(f"{self.__class__.__name__}")
|
|
139
|
+
|
|
140
|
+
# Log initialization with masked token
|
|
141
|
+
masked_token = mask_token(self._bearer_token)
|
|
142
|
+
if self.debug:
|
|
143
|
+
self.logger.info(
|
|
144
|
+
f"MeilisearchClient initialized with token: {masked_token}"
|
|
145
|
+
)
|
|
146
|
+
self.logger.info(
|
|
147
|
+
f"Retry config: {self.retry_config.max_attempts} attempts, "
|
|
148
|
+
f"timeout: {self.timeout_config.total_timeout}s"
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
self.logger.info("MeilisearchClient initialized successfully")
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def bearer_token(self) -> str:
|
|
155
|
+
"""Get the bearer token."""
|
|
156
|
+
return self._bearer_token
|
|
157
|
+
|
|
158
|
+
def multi_search(
|
|
159
|
+
self,
|
|
160
|
+
queries: Sequence[MultiSearchQuery] | None = None,
|
|
161
|
+
cached_session: Client | None = None,
|
|
162
|
+
) -> MultiSearchResults | None:
|
|
163
|
+
key = _make_cache_key(queries)
|
|
164
|
+
cached = _cache_get(key)
|
|
165
|
+
if cached is not None:
|
|
166
|
+
return _result_from_cached_payload(cached)
|
|
167
|
+
|
|
168
|
+
url = f"{self.url}{MEILISEARCH_ENDPOINT_MULTI_SEARCH}"
|
|
169
|
+
params = {"queries": [query.to_dict() for query in queries] if queries else []}
|
|
170
|
+
raw_data = catch_result(
|
|
171
|
+
lambda: http_post_json(
|
|
172
|
+
url,
|
|
173
|
+
self.headers,
|
|
174
|
+
params,
|
|
175
|
+
debug=self.debug,
|
|
176
|
+
cached_session=cached_session or self.cached_session,
|
|
177
|
+
retry_config=self.retry_config,
|
|
178
|
+
timeout_config=self.timeout_config,
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
result = MultiSearchResults.from_dict(raw_data) if raw_data else None
|
|
182
|
+
if result is not None:
|
|
183
|
+
_cache_result_payload(key, result)
|
|
184
|
+
return result
|
|
185
|
+
|
|
186
|
+
async def multi_search_async(
|
|
187
|
+
self,
|
|
188
|
+
queries: Sequence[MultiSearchQuery] | None = None,
|
|
189
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
190
|
+
) -> MultiSearchResults | None:
|
|
191
|
+
key = _make_cache_key(queries)
|
|
192
|
+
cached = _cache_get(key)
|
|
193
|
+
if cached is not None:
|
|
194
|
+
return _result_from_cached_payload(cached)
|
|
195
|
+
|
|
196
|
+
url = f"{self.url}{MEILISEARCH_ENDPOINT_MULTI_SEARCH}"
|
|
197
|
+
params = {"queries": [query.to_dict() for query in queries] if queries else []}
|
|
198
|
+
try:
|
|
199
|
+
raw_data = await http_post_json_async(
|
|
200
|
+
url,
|
|
201
|
+
self.headers,
|
|
202
|
+
params,
|
|
203
|
+
debug=self.debug,
|
|
204
|
+
cached_session=cached_session or self.async_cached_session,
|
|
205
|
+
retry_config=self.retry_config,
|
|
206
|
+
timeout_config=self.timeout_config,
|
|
207
|
+
)
|
|
208
|
+
result = MultiSearchResults.from_dict(raw_data) if raw_data else None
|
|
209
|
+
except (httpx.HTTPStatusError, httpx.RequestError) as e:
|
|
210
|
+
self.logger.warning("multi_search_async request failed: %s", e)
|
|
211
|
+
result = None
|
|
212
|
+
except Exception as e:
|
|
213
|
+
self.logger.error("multi_search_async unexpected error: %s", e)
|
|
214
|
+
result = None
|
|
215
|
+
|
|
216
|
+
if result is not None:
|
|
217
|
+
_cache_result_payload(key, result)
|
|
218
|
+
return result
|