Fix: Consolidate divergent _since_unix implementations (T-09)
Consolidate the two divergent implementations of _since_unix from ban_service.py and history_service.py into a single shared utility function in time_utils.py. Changes: - Move _since_unix to app/utils/time_utils.py with consistent time.time() approach - Move TIME_RANGE_SLACK_SECONDS constant to app/utils/constants.py - Update ban_service.py to import since_unix from time_utils - Update history_service.py to import since_unix from time_utils - Both services now use the same window boundary calculation with 60-second slack - Add comprehensive tests for the shared since_unix function - Document timestamp handling rationale in Backend-Development.md This ensures dashboard and history queries return consistent row counts for the same time range by using the same timestamp calculation and slack window across all services. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -15,7 +15,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import structlog
|
||||
|
||||
from app.models.ban import TIME_RANGE_SECONDS, BanOrigin, TimeRange
|
||||
from app.models.ban import BanOrigin, TimeRange
|
||||
from app.services import geo_service
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -35,6 +35,7 @@ from app.repositories import history_archive_repo as default_history_archive_rep
|
||||
from app.services.fail2ban_metadata_service import default_fail2ban_metadata_service
|
||||
from app.utils.constants import DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE
|
||||
from app.utils.fail2ban_db_utils import parse_data_json, ts_to_iso
|
||||
from app.utils.time_utils import since_unix
|
||||
|
||||
log: structlog.stdlib.BoundLogger = structlog.get_logger()
|
||||
|
||||
@@ -43,25 +44,11 @@ async def get_fail2ban_db_path(socket_path: str) -> str:
|
||||
"""Return the fail2ban database path using the shared metadata cache."""
|
||||
return await default_fail2ban_metadata_service.get_db_path(socket_path)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Constants
|
||||
# Internal Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _since_unix(range_: TimeRange) -> int:
|
||||
"""Return the Unix timestamp for the start of the given time window.
|
||||
|
||||
Args:
|
||||
range_: One of the supported time-range presets.
|
||||
|
||||
Returns:
|
||||
Unix timestamp (seconds since epoch) equal to *now − range_*.
|
||||
"""
|
||||
seconds: int = TIME_RANGE_SECONDS[range_]
|
||||
return int(datetime.now(tz=UTC).timestamp()) - seconds
|
||||
|
||||
|
||||
async def _resolve_geo_info(
|
||||
ip: str,
|
||||
*,
|
||||
@@ -199,7 +186,7 @@ async def list_history(
|
||||
# Build WHERE clauses dynamically.
|
||||
since: int | None = None
|
||||
if range_ is not None:
|
||||
since = _since_unix(range_)
|
||||
since = since_unix(range_)
|
||||
|
||||
db_path: str = await get_fail2ban_db_path(socket_path)
|
||||
log.info(
|
||||
|
||||
Reference in New Issue
Block a user