Spaces:
Sleeping
Sleeping
| # COST: ZERO OpenAI chat tokens. | |
| # Scraping is plain HTTP + BeautifulSoup. Diff checking uses difflib (stdlib). | |
| # is_content_stale() is checked first β if content is fresh the job returns | |
| # immediately, skipping both the HTTP fetch and re-indexing. | |
| # Re-indexing (ingest_scraped_content) calls text-embedding-3-small for new | |
| # chunks only β one-time embedding cost, no chat LLM. | |
| import logging | |
| from apscheduler.schedulers.asyncio import AsyncIOScheduler | |
| from ingestion import ingest_scraped_content | |
| from scraper.content_store import ( | |
| get_content_diff, | |
| is_content_stale, | |
| is_multi_page_stale, | |
| load_latest_content, | |
| save_all_pages, | |
| save_site_content, | |
| ) | |
| from scraper.web_scraper import AGENTRAX_URL, scrape_all_pages, scrape_site | |
| logger = logging.getLogger(__name__) | |
| _scheduler: AsyncIOScheduler | None = None | |
| async def refresh_agentrax_content() -> None: | |
| # ββ Homepage (single-page store, backward compat) ββββββββββββββββββββββββ | |
| if not is_content_stale(): | |
| logger.info("Homepage content is fresh β skipping single-page refresh.") | |
| else: | |
| logger.info("Scraping homepage %s ...", AGENTRAX_URL) | |
| data = await scrape_site(AGENTRAX_URL) | |
| if "error" in data: | |
| logger.error("Homepage scrape failed: %s", data["error"]) | |
| else: | |
| previous = load_latest_content() | |
| if previous: | |
| diff = get_content_diff(previous, data) | |
| if diff["is_changed"]: | |
| logger.warning("HOMEPAGE UPDATED: %s", diff["summary_of_changes"]) | |
| save_site_content(data) | |
| ingest_scraped_content(data) | |
| logger.info("Homepage refreshed and re-indexed.") | |
| # ββ All pages (multi-page store) βββββββββββββββββββββββββββββββββββββββββ | |
| if not is_multi_page_stale(): | |
| logger.info("Multi-page content is fresh β skipping full-site refresh.") | |
| return | |
| logger.info("Scraping all AgentRax pages...") | |
| pages = await scrape_all_pages() | |
| if not pages: | |
| logger.error("Full-site scrape returned no results.") | |
| return | |
| save_all_pages(pages) | |
| for page in pages: | |
| ingest_scraped_content(page) | |
| logger.info("Full site refreshed: %d page(s) scraped and indexed.", len(pages)) | |
| def start_scheduler() -> None: | |
| global _scheduler | |
| _scheduler = AsyncIOScheduler() | |
| _scheduler.add_job( | |
| refresh_agentrax_content, | |
| trigger="interval", | |
| minutes=60, | |
| id="refresh_agentrax", | |
| replace_existing=True, | |
| ) | |
| _scheduler.start() | |
| logger.info("Scheduler started β refresh every 60 minutes.") | |
| import asyncio | |
| asyncio.get_event_loop().create_task(refresh_agentrax_content()) | |
| def stop_scheduler() -> None: | |
| global _scheduler | |
| if _scheduler and _scheduler.running: | |
| _scheduler.shutdown(wait=False) | |
| logger.info("Scheduler stopped.") | |