From 44aef147b5d7d4a1f8c9eb7f910045724185b254 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Tue, 20 May 2025 11:03:02 -0300 Subject: [PATCH 1/5] debug: moved precache to background to avoid stucking ... --- .gitea/workflows/main.yml | 2 +- main.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/main.yml b/.gitea/workflows/main.yml index f65ae48a..04bc35d9 100644 --- a/.gitea/workflows/main.yml +++ b/.gitea/workflows/main.yml @@ -35,7 +35,7 @@ jobs: ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} - name: Push to dokku for staging branch - if: github.ref == 'refs/heads/staging' + if: github.ref == 'refs/heads/feat/sv-search-v4' uses: dokku/github-action@master with: branch: 'dev' diff --git a/main.py b/main.py index 536dfdc2..6e6034e2 100644 --- a/main.py +++ b/main.py @@ -17,7 +17,6 @@ from cache.revalidator import revalidation_manager from services.exception import ExceptionHandlerMiddleware from services.redis import redis from services.schema import create_all_tables, resolvers -#from services.search import search_service from services.search import search_service, initialize_search_index from services.viewed import ViewedStorage from services.webhook import WebhookEndpoint, create_webhook_endpoint @@ -53,9 +52,10 @@ async def lifespan(_app): try: print("[lifespan] Starting application initialization") create_all_tables() + # schedule precaching in background to avoid blocking startup + asyncio.create_task(precache_data()) await asyncio.gather( redis.connect(), - precache_data(), ViewedStorage.init(), create_webhook_endpoint(), check_search_service(), From 1ada0a02f9fa6a18a2bbfa38dcfa91adb292d060 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Tue, 20 May 2025 11:19:58 -0300 Subject: [PATCH 2/5] debug: with timeout for prechashing --- main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 6e6034e2..f01cbd90 100644 --- a/main.py +++ b/main.py @@ -52,8 +52,13 @@ async def lifespan(_app): try: print("[lifespan] Starting application initialization") create_all_tables() + # schedule precaching in background to avoid blocking startup - asyncio.create_task(precache_data()) + asyncio.create_task( + asyncio.wait_for(precache_data(), timeout=60) + .catch(asyncio.TimeoutError, lambda _: print("Precache timed out")) + ) + await asyncio.gather( redis.connect(), ViewedStorage.init(), From 80b909d801933afd891f72ea281846c8ec000474 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Tue, 20 May 2025 11:23:00 -0300 Subject: [PATCH 3/5] debug: with logs in prechashing process --- cache/precache.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cache/precache.py b/cache/precache.py index 23844024..2095c537 100644 --- a/cache/precache.py +++ b/cache/precache.py @@ -77,11 +77,15 @@ async def precache_topics_followers(topic_id: int, session): async def precache_data(): logger.info("precaching...") + logger.debug("Entering precache_data") try: key = "authorizer_env" + logger.debug(f"Fetching existing hash for key '{key}' from Redis") # cache reset value = await redis.execute("HGETALL", key) + logger.debug(f"Fetched value for '{key}': {value}") await redis.execute("FLUSHDB") + logger.debug("Redis database flushed") logger.info("redis: FLUSHDB") # Преобразуем словарь в список аргументов для HSET @@ -97,21 +101,27 @@ async def precache_data(): await redis.execute("HSET", key, *value) logger.info(f"redis hash '{key}' was restored") + logger.info("Beginning topic precache phase") with local_session() as session: # topics q = select(Topic).where(Topic.community == 1) topics = get_with_stat(q) + logger.info(f"Found {len(topics)} topics to precache") for topic in topics: topic_dict = topic.dict() if hasattr(topic, "dict") else topic + logger.debug(f"Precaching topic id={topic_dict.get('id')}") await cache_topic(topic_dict) + logger.debug(f"Cached topic id={topic_dict.get('id')}") await asyncio.gather( precache_topics_followers(topic_dict["id"], session), precache_topics_authors(topic_dict["id"], session), ) + logger.debug(f"Finished precaching followers and authors for topic id={topic_dict.get('id')}") logger.info(f"{len(topics)} topics and their followings precached") # authors authors = get_with_stat(select(Author).where(Author.user.is_not(None))) + logger.info(f"Found {len(authors)} authors to precache") logger.info(f"{len(authors)} authors found in database") for author in authors: if isinstance(author, Author): @@ -119,10 +129,12 @@ async def precache_data(): author_id = profile.get("id") user_id = profile.get("user", "").strip() if author_id and user_id: + logger.debug(f"Precaching author id={author_id}") await cache_author(profile) await asyncio.gather( precache_authors_followers(author_id, session), precache_authors_follows(author_id, session) ) + logger.debug(f"Finished precaching followers and follows for author id={author_id}") else: logger.error(f"fail caching {author}") logger.info(f"{len(authors)} authors and their followings precached") From 82870a4e4777ef99a3d00f0792df9d484853683a Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Tue, 20 May 2025 11:26:30 -0300 Subject: [PATCH 4/5] debug: prechase wrapped for time out --- main.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index f01cbd90..581c6085 100644 --- a/main.py +++ b/main.py @@ -42,6 +42,15 @@ async def check_search_service(): else: print(f"[INFO] Search service is available: {info}") +# Helper to run precache with timeout and catch errors +async def precache_with_timeout(): + try: + await asyncio.wait_for(precache_data(), timeout=60) + except asyncio.TimeoutError: + print("[precache] Precache timed out after 60 seconds") + except Exception as e: + print(f"[precache] Error during precache: {e}") + # indexing DB data # async def indexing(): @@ -53,11 +62,8 @@ async def lifespan(_app): print("[lifespan] Starting application initialization") create_all_tables() - # schedule precaching in background to avoid blocking startup - asyncio.create_task( - asyncio.wait_for(precache_data(), timeout=60) - .catch(asyncio.TimeoutError, lambda _: print("Precache timed out")) - ) + # schedule precaching in background with timeout and error handling + asyncio.create_task(precache_with_timeout()) await asyncio.gather( redis.connect(), From e1d1096674eadbd48239c9e24686f609c09f2de0 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Mon, 2 Jun 2025 18:17:24 -0300 Subject: [PATCH 5/5] feat: without staging deploying by gitea --- .gitea/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/main.yml b/.gitea/workflows/main.yml index 04bc35d9..f65ae48a 100644 --- a/.gitea/workflows/main.yml +++ b/.gitea/workflows/main.yml @@ -35,7 +35,7 @@ jobs: ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} - name: Push to dokku for staging branch - if: github.ref == 'refs/heads/feat/sv-search-v4' + if: github.ref == 'refs/heads/staging' uses: dokku/github-action@master with: branch: 'dev'