feat: schedule periodic user synchronization
This commit is contained in:
42
tests/sync/test_scheduler.py
Normal file
42
tests/sync/test_scheduler.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import asyncio
|
||||
|
||||
import pytest
|
||||
|
||||
from app.sync.scheduler import SyncScheduler
|
||||
|
||||
|
||||
class FakeSyncManager:
|
||||
def __init__(self, results=None) -> None:
|
||||
self.results = results if results is not None else []
|
||||
self.calls = 0
|
||||
|
||||
async def sync_all_enabled(self):
|
||||
self.calls += 1
|
||||
if self.results and isinstance(self.results[0], Exception):
|
||||
raise self.results[0]
|
||||
return list(self.results)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scheduler_calls_sync_all_and_survives_failure() -> None:
|
||||
fake = FakeSyncManager(results=[RuntimeError("one user failed")])
|
||||
scheduler = SyncScheduler(fake, interval_seconds=0.01)
|
||||
await scheduler.start()
|
||||
await asyncio.sleep(0.035)
|
||||
await scheduler.stop()
|
||||
assert fake.calls >= 2
|
||||
assert scheduler.last_tick is not None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scheduler_stop_cancels_the_loop() -> None:
|
||||
fake = FakeSyncManager()
|
||||
scheduler = SyncScheduler(fake, interval_seconds=0.01)
|
||||
await scheduler.start()
|
||||
await asyncio.sleep(0.035)
|
||||
await scheduler.stop()
|
||||
|
||||
assert scheduler._task is None
|
||||
calls_after_stop = fake.calls
|
||||
await asyncio.sleep(0.05)
|
||||
assert fake.calls == calls_after_stop
|
||||
30
tests/test_main_lifespan.py
Normal file
30
tests/test_main_lifespan.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography.fernet import Fernet
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.config import Settings
|
||||
from app.main import create_app
|
||||
from app.sync.manager import SyncManager
|
||||
|
||||
|
||||
def test_lifespan_wires_sync_manager_and_scheduler(tmp_path: Path) -> None:
|
||||
settings = Settings(
|
||||
ADMIN_PASSWORD="admin-secret",
|
||||
SECRET_KEY="0123456789abcdef0123456789abcdef",
|
||||
CREDENTIAL_ENCRYPTION_KEY=Fernet.generate_key().decode("ascii"),
|
||||
DATA_DIR=str(tmp_path),
|
||||
DATABASE_URL=f"sqlite:///{tmp_path / 'app.db'}",
|
||||
SYNC_INTERVAL_MINUTES=5,
|
||||
)
|
||||
app = create_app(settings)
|
||||
|
||||
# No users are seeded in this database, so sync_all_enabled() has nothing
|
||||
# to iterate over and the real MyWhoosh/Garmin factories are never invoked.
|
||||
with TestClient(app):
|
||||
assert app.state.sync_manager is not None
|
||||
assert isinstance(app.state.sync_manager, SyncManager)
|
||||
assert app.state.scheduler is not None
|
||||
assert app.state.scheduler.last_tick is not None
|
||||
|
||||
app.state.db_engine.dispose()
|
||||
Reference in New Issue
Block a user