mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 13:53:15 +00:00
89 lines
2.7 KiB
Python
89 lines
2.7 KiB
Python
|
|
"""One-time backfill: delete expired ``thread_wakeup`` crons from a deployment.
|
||
|
|
|
||
|
|
One-shot wakeup crons set an ``end_time`` that stops them re-firing, but the
|
||
|
|
cron row is never removed, so dead rows accumulate. The ``schedule_thread_wakeup``
|
||
|
|
tool now purges these opportunistically; this script clears the backlog.
|
||
|
|
|
||
|
|
Usage:
|
||
|
|
uv run python scripts/purge_wakeup_crons.py --dry-run
|
||
|
|
uv run python scripts/purge_wakeup_crons.py
|
||
|
|
|
||
|
|
Resolves the deployment URL from ``--url`` or ``LANGGRAPH_URL`` / ``LANGGRAPH_URL_PROD``,
|
||
|
|
and the API key from ``LANGGRAPH_API_KEY`` / ``LANGSMITH_API_KEY`` / ``LANGSMITH_API_KEY_PROD``.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
import asyncio
|
||
|
|
import logging
|
||
|
|
import os
|
||
|
|
from datetime import UTC, datetime
|
||
|
|
|
||
|
|
from langgraph_sdk import get_client
|
||
|
|
|
||
|
|
from agent.tools.schedule_thread_wakeup import (
|
||
|
|
find_expired_wakeup_cron_ids,
|
||
|
|
purge_expired_wakeup_crons,
|
||
|
|
)
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
def _load_dotenv_if_available() -> None:
|
||
|
|
try:
|
||
|
|
from dotenv import load_dotenv
|
||
|
|
except ImportError:
|
||
|
|
return
|
||
|
|
load_dotenv()
|
||
|
|
|
||
|
|
|
||
|
|
def _resolve_url(arg_url: str | None) -> str:
|
||
|
|
url = arg_url or os.environ.get("LANGGRAPH_URL") or os.environ.get("LANGGRAPH_URL_PROD")
|
||
|
|
if not url:
|
||
|
|
raise RuntimeError("Set --url or LANGGRAPH_URL / LANGGRAPH_URL_PROD")
|
||
|
|
return url
|
||
|
|
|
||
|
|
|
||
|
|
def _resolve_api_key() -> str | None:
|
||
|
|
return (
|
||
|
|
os.environ.get("LANGGRAPH_API_KEY")
|
||
|
|
or os.environ.get("LANGSMITH_API_KEY")
|
||
|
|
or os.environ.get("LANGSMITH_API_KEY_PROD")
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def _run(url: str, api_key: str | None, dry_run: bool) -> None:
|
||
|
|
client = get_client(url=url, api_key=api_key)
|
||
|
|
now = datetime.now(UTC)
|
||
|
|
if dry_run:
|
||
|
|
expired = await find_expired_wakeup_cron_ids(client, now=now)
|
||
|
|
logger.info("[dry-run] %d expired thread_wakeup cron(s) would be deleted", len(expired))
|
||
|
|
for cron_id in expired:
|
||
|
|
logger.info(" %s", cron_id)
|
||
|
|
return
|
||
|
|
deleted = await purge_expired_wakeup_crons(client, now=now)
|
||
|
|
logger.info("Deleted %d expired thread_wakeup cron(s)", deleted)
|
||
|
|
|
||
|
|
|
||
|
|
def parse_args() -> argparse.Namespace:
|
||
|
|
parser = argparse.ArgumentParser(description="Purge expired thread_wakeup crons.")
|
||
|
|
parser.add_argument("--url", default=None, help="Deployment URL (defaults to env).")
|
||
|
|
parser.add_argument(
|
||
|
|
"--dry-run",
|
||
|
|
action="store_true",
|
||
|
|
help="List the crons that would be deleted without deleting them.",
|
||
|
|
)
|
||
|
|
return parser.parse_args()
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> None:
|
||
|
|
_load_dotenv_if_available()
|
||
|
|
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
||
|
|
args = parse_args()
|
||
|
|
asyncio.run(_run(_resolve_url(args.url), _resolve_api_key(), args.dry_run))
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|