| 157 | return post_data, cache_used |
| 158 | |
| 159 | async def query( |
| 160 | self, |
| 161 | post_id: str, |
| 162 | use_cache: bool = True, |
| 163 | retry: int = 2, |
| 164 | force_cache: bool = False, |
| 165 | ): |
| 166 | logger.debug(f"Medium QUERY: {use_cache=}, {retry=}, {force_cache=}") |
| 167 | |
| 168 | post_data, is_cache_used = None, False |
| 169 | |
| 170 | attempt = 0 |
| 171 | reason = None |
| 172 | while not post_data and attempt < retry: |
| 173 | try: |
| 174 | post_data, is_cache_used = await self.query_get( |
| 175 | post_id, use_cache, force_cache |
| 176 | ) |
| 177 | |
| 178 | if not post_data: |
| 179 | reason = "No post data returned" |
| 180 | elif not isinstance(post_data, dict): |
| 181 | reason = f"Post data is not a dictionary: {post_data=}" |
| 182 | elif post_data.get("error"): |
| 183 | reason = f"Post data contains an error: {post_data=}" |
| 184 | elif not post_data.get("data"): |
| 185 | reason = f"Post data missing 'data' key: {post_data=}" |
| 186 | elif not post_data.get("data", {}).get("post"): |
| 187 | reason = f"Post data missing 'data.post' key: {post_data=}" |
| 188 | |
| 189 | if reason is None: |
| 190 | logger.debug("Post data was successfully queried") |
| 191 | break |
| 192 | except Exception as e: |
| 193 | logger.error(f"Attempt {attempt + 1} failed with exception: {e}") |
| 194 | logger.debug(f"Retrying in {2 ** attempt} seconds...") |
| 195 | await asyncio.sleep(2**attempt) |
| 196 | finally: |
| 197 | attempt += 1 |
| 198 | else: |
| 199 | if not reason: |
| 200 | reason = "Unknown" |
| 201 | |
| 202 | raise MediumPostQueryError( |
| 203 | f"Could not query post by ID from API: {post_id}. Reason: {reason}" |
| 204 | ) |
| 205 | |
| 206 | if not is_cache_used: |
| 207 | logger.debug("Pushing post data to cache") |
| 208 | self.cache.push(post_id, post_data) |
| 209 | |
| 210 | logger.trace("Query: done") |
| 211 | return post_data |
| 212 | |
| 213 | def _parse_and_render_content_html_post( |
| 214 | self, |