chore: initialize EverOS 1.0.0
md-first memory extraction framework for AI agents. Markdown is the single source of truth; SQLite holds state and LanceDB provides the rebuildable vector + BM25 + scalar index. The codebase follows a single-direction DDD layering (entrypoints -> service -> memory -> infra, with component / core / config cross-cutting) enforced by import-linter. Engineering surface: - Coding conventions in .claude/rules/ (path-scoped) and workflows in .claude/skills/ (/commit, /new-branch, /pr). - GitHub Actions CI runs make lint + test + integration; pre-commit mirrors the gates locally (ruff, hygiene hooks, gitlint commit-msg). - Commit messages follow Conventional Commits, enforced by gitlint. - make lint also enforces datetime two-zone discipline and OpenAPI drift.
This commit is contained in:
0
tests/unit/test_core/test_lifespan/__init__.py
Normal file
0
tests/unit/test_core/test_lifespan/__init__.py
Normal file
88
tests/unit/test_core/test_lifespan/test_factory.py
Normal file
88
tests/unit/test_core/test_lifespan/test_factory.py
Normal file
@ -0,0 +1,88 @@
|
||||
"""``build_lifespan`` — provider ordering, state storage, shutdown errors."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from everos.core.lifespan import LifespanProvider
|
||||
from everos.core.lifespan.factory import build_lifespan
|
||||
|
||||
|
||||
class _RecordingProvider(LifespanProvider):
|
||||
"""Provider that records the order in which startup/shutdown ran."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
order: int,
|
||||
log: list[str],
|
||||
*,
|
||||
returns: object | None = None,
|
||||
shutdown_raises: bool = False,
|
||||
) -> None:
|
||||
super().__init__(name=name, order=order)
|
||||
self._log = log
|
||||
self._returns = returns
|
||||
self._shutdown_raises = shutdown_raises
|
||||
|
||||
async def startup(self, app: FastAPI) -> object | None:
|
||||
self._log.append(f"start:{self.name}")
|
||||
return self._returns
|
||||
|
||||
async def shutdown(self, app: FastAPI) -> None:
|
||||
self._log.append(f"stop:{self.name}")
|
||||
if self._shutdown_raises:
|
||||
raise RuntimeError(f"{self.name} shutdown boom")
|
||||
|
||||
|
||||
async def test_startup_runs_in_order_ascending() -> None:
|
||||
log: list[str] = []
|
||||
p1 = _RecordingProvider("a", order=2, log=log)
|
||||
p2 = _RecordingProvider("b", order=1, log=log)
|
||||
p3 = _RecordingProvider("c", order=3, log=log)
|
||||
|
||||
app = FastAPI()
|
||||
async with build_lifespan([p1, p2, p3])(app):
|
||||
pass
|
||||
assert log[:3] == ["start:b", "start:a", "start:c"]
|
||||
|
||||
|
||||
async def test_shutdown_runs_in_reverse_order() -> None:
|
||||
log: list[str] = []
|
||||
p1 = _RecordingProvider("a", order=1, log=log)
|
||||
p2 = _RecordingProvider("b", order=2, log=log)
|
||||
|
||||
app = FastAPI()
|
||||
async with build_lifespan([p1, p2])(app):
|
||||
pass
|
||||
# shutdown phase: reverse of startup
|
||||
assert log[2:] == ["stop:b", "stop:a"]
|
||||
|
||||
|
||||
async def test_non_none_startup_result_stored_in_state() -> None:
|
||||
sentinel = object()
|
||||
p = _RecordingProvider("x", order=1, log=[], returns=sentinel)
|
||||
app = FastAPI()
|
||||
async with build_lifespan([p])(app):
|
||||
assert app.state.lifespan_data["x"] is sentinel
|
||||
|
||||
|
||||
async def test_none_startup_result_not_stored() -> None:
|
||||
p = _RecordingProvider("nullone", order=1, log=[], returns=None)
|
||||
app = FastAPI()
|
||||
async with build_lifespan([p])(app):
|
||||
assert "nullone" not in app.state.lifespan_data
|
||||
|
||||
|
||||
async def test_shutdown_exception_swallowed_and_logged() -> None:
|
||||
"""Failed shutdown logs but doesn't break sibling shutdown."""
|
||||
log: list[str] = []
|
||||
p1 = _RecordingProvider("a", order=1, log=log)
|
||||
p2 = _RecordingProvider("b", order=2, log=log, shutdown_raises=True)
|
||||
|
||||
app = FastAPI()
|
||||
async with build_lifespan([p1, p2])(app):
|
||||
pass
|
||||
# Even though "b" raised, "a" still shut down.
|
||||
assert log[-1] == "stop:a"
|
||||
assert "stop:b" in log # b's shutdown ran (and raised, but swallowed)
|
||||
35
tests/unit/test_core/test_lifespan/test_metrics_lifespan.py
Normal file
35
tests/unit/test_core/test_lifespan/test_metrics_lifespan.py
Normal file
@ -0,0 +1,35 @@
|
||||
"""``MetricsLifespanProvider`` — startup returns registry, shutdown logs."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import FastAPI
|
||||
from prometheus_client import CollectorRegistry
|
||||
|
||||
from everos.core.lifespan.metrics_lifespan import MetricsLifespanProvider
|
||||
from everos.core.observability.metrics import (
|
||||
reset_metrics_registry,
|
||||
set_metrics_registry,
|
||||
)
|
||||
|
||||
|
||||
async def test_startup_returns_registry() -> None:
|
||||
fresh = CollectorRegistry()
|
||||
set_metrics_registry(fresh)
|
||||
try:
|
||||
p = MetricsLifespanProvider()
|
||||
result = await p.startup(FastAPI())
|
||||
assert result is fresh
|
||||
finally:
|
||||
reset_metrics_registry()
|
||||
|
||||
|
||||
async def test_shutdown_is_noop() -> None:
|
||||
# Smoke test — must not raise.
|
||||
p = MetricsLifespanProvider()
|
||||
await p.shutdown(FastAPI())
|
||||
|
||||
|
||||
def test_provider_metadata() -> None:
|
||||
p = MetricsLifespanProvider(order=42)
|
||||
assert p.name == "metrics"
|
||||
assert p.order == 42
|
||||
Reference in New Issue
Block a user