存储或更新凭证
(self, filename: str, credential_data: Dict[str, Any], mode: str = "geminicli")
| 337 | # ============ StorageBackend 协议方法 ============ |
| 338 | |
| 339 | async def store_credential(self, filename: str, credential_data: Dict[str, Any], mode: str = "geminicli") -> bool: |
| 340 | """存储或更新凭证""" |
| 341 | self._ensure_initialized() |
| 342 | filename = os.path.basename(filename) |
| 343 | |
| 344 | try: |
| 345 | table_name = self._get_table_name(mode) |
| 346 | async with self._pool.acquire() as conn: |
| 347 | existing = await conn.fetchrow( |
| 348 | f"SELECT rotation_order FROM {table_name} WHERE filename = $1", filename |
| 349 | ) |
| 350 | |
| 351 | if existing: |
| 352 | await conn.execute( |
| 353 | f""" |
| 354 | UPDATE {table_name} |
| 355 | SET credential_data = $1, |
| 356 | updated_at = EXTRACT(EPOCH FROM NOW()) |
| 357 | WHERE filename = $2 |
| 358 | """, |
| 359 | json.dumps(credential_data), filename |
| 360 | ) |
| 361 | else: |
| 362 | row = await conn.fetchrow( |
| 363 | f"SELECT COALESCE(MAX(rotation_order), -1) + 1 AS next_order FROM {table_name}" |
| 364 | ) |
| 365 | next_order = row["next_order"] |
| 366 | await conn.execute( |
| 367 | f""" |
| 368 | INSERT INTO {table_name} |
| 369 | (filename, credential_data, rotation_order, last_success) |
| 370 | VALUES ($1, $2, $3, $4) |
| 371 | """, |
| 372 | filename, json.dumps(credential_data), next_order, time.time() |
| 373 | ) |
| 374 | |
| 375 | log.debug(f"Stored credential: {filename} (mode={mode})") |
| 376 | return True |
| 377 | |
| 378 | except Exception as e: |
| 379 | log.error(f"Error storing credential {filename}: {e}") |
| 380 | return False |
| 381 | |
| 382 | async def get_credential(self, filename: str, mode: str = "geminicli") -> Optional[Dict[str, Any]]: |
| 383 | """获取凭证数据""" |