|
1 | 1 | """Utilities for connecting to and managing Redis connections.""" |
2 | 2 |
|
3 | | -from typing import Optional |
| 3 | +import logging |
| 4 | +from typing import Dict, List, Optional |
4 | 5 |
|
| 6 | +from fastapi import Request |
5 | 7 | from pydantic_settings import BaseSettings |
6 | 8 | from redis import asyncio as aioredis |
7 | 9 | from redis.asyncio.sentinel import Sentinel |
8 | 10 |
|
| 11 | +from stac_fastapi.core.utilities import get_bool_env |
| 12 | + |
9 | 13 | redis_pool: Optional[aioredis.Redis] = None |
10 | 14 |
|
| 15 | +logger = logging.getLogger(__name__) |
| 16 | + |
11 | 17 |
|
12 | 18 | class RedisSentinelSettings(BaseSettings): |
13 | 19 | """Configuration for connecting to Redis Sentinel.""" |
@@ -122,3 +128,53 @@ async def get_prev_link(redis: aioredis.Redis, token: Optional[str]) -> Optional |
122 | 128 | if not token: |
123 | 129 | return None |
124 | 130 | return await redis.get(f"nav:self:{token}") |
| 131 | + |
| 132 | + |
| 133 | +async def handle_redis_pagination( |
| 134 | + request: Request, |
| 135 | + links: List[Dict], |
| 136 | + next_token: Optional[str] = None, |
| 137 | + current_token: Optional[str] = None, |
| 138 | + redis_enable: Optional[bool] = None, |
| 139 | +) -> None: |
| 140 | + """ |
| 141 | + Handle Redis-based pagination for both items and collections. |
| 142 | +
|
| 143 | + Args: |
| 144 | + request: FastAPI request object |
| 145 | + links: Links array to modify |
| 146 | + next_token: Token for the next page (used to save current URL) |
| 147 | + current_token: Current page token (used to retrieve previous page) |
| 148 | + redis_enable: Whether Redis is enabled (auto-detected if None) |
| 149 | + """ |
| 150 | + # Auto-detect Redis enablement if not provided |
| 151 | + if redis_enable is None: |
| 152 | + redis_enable = get_bool_env("REDIS_ENABLE", default=False) |
| 153 | + |
| 154 | + if not redis_enable: |
| 155 | + return |
| 156 | + |
| 157 | + try: |
| 158 | + redis = await connect_redis() |
| 159 | + logger.info("Redis connection established successfully") |
| 160 | + |
| 161 | + # Save current URL for next page's previous link |
| 162 | + if next_token: |
| 163 | + self_link = str(request.url) |
| 164 | + await save_self_link(redis, next_token, self_link) |
| 165 | + |
| 166 | + # Get previous page link if available |
| 167 | + if current_token: |
| 168 | + prev_link = await get_prev_link(redis, current_token) |
| 169 | + if prev_link: |
| 170 | + links.insert( |
| 171 | + 0, |
| 172 | + { |
| 173 | + "rel": "prev", |
| 174 | + "type": "application/json", |
| 175 | + "method": "GET", |
| 176 | + "href": prev_link, |
| 177 | + }, |
| 178 | + ) |
| 179 | + except Exception as e: |
| 180 | + logger.warning(f"Redis connection failed, continuing without Redis: {e}") |
0 commit comments