from __future__ import annotations import asyncio from sqlalchemy import select from app.core.logger import make_log from app.core.models.node_storage import StoredContent from app.core.network.dht import dht_config from app.core.storage import db_session async def replication_daemon(app): await asyncio.sleep(5) memory = getattr(app.ctx, "memory", None) if not memory: make_log("Replication", "No memory context; replication daemon exiting", level="warning") return make_log("Replication", "daemon started") while True: try: membership_state = memory.membership.state async with db_session(auto_commit=False) as session: rows = await session.execute(select(StoredContent.hash)) content_hashes = [row[0] for row in rows.all()] for content_hash in content_hashes: try: state = memory.replication.ensure_replication(content_hash, membership_state) memory.replication.heartbeat(content_hash, memory.node_id) make_log("Replication", f"Replicated {content_hash} leader={state.leader}", level="debug") except Exception as exc: make_log("Replication", f"ensure failed for {content_hash}: {exc}", level="warning") except Exception as exc: make_log("Replication", f"daemon iteration failed: {exc}", level="error") await asyncio.sleep(dht_config.heartbeat_interval) async def heartbeat_daemon(app): await asyncio.sleep(dht_config.heartbeat_interval // 2) memory = getattr(app.ctx, "memory", None) if not memory: return while True: try: async with db_session(auto_commit=False) as session: rows = await session.execute(select(StoredContent.hash)) content_hashes = [row[0] for row in rows.all()] for content_hash in content_hashes: memory.replication.heartbeat(content_hash, memory.node_id) except Exception as exc: make_log("Replication", f"heartbeat failed: {exc}", level="warning") await asyncio.sleep(dht_config.heartbeat_interval)