45 lines
1.3 KiB
Python
45 lines
1.3 KiB
Python
from datetime import datetime
|
|
|
|
import asyncpg
|
|
|
|
from utils.read.models import CaptureGap, CaptureStatus
|
|
|
|
_STATUS = """
|
|
SELECT started_at, seen_at, seen_at >= now() - interval '150 seconds' AS live
|
|
FROM capture_uptime WHERE account_id = $1
|
|
ORDER BY started_at DESC LIMIT 1
|
|
"""
|
|
|
|
_GAPS = """
|
|
SELECT seen_at AS start, next_start AS "end"
|
|
FROM (
|
|
SELECT seen_at,
|
|
lead(started_at) OVER (ORDER BY started_at) AS next_start
|
|
FROM capture_uptime WHERE account_id = $1
|
|
) stretches
|
|
WHERE next_start - seen_at > interval '30 minutes'
|
|
AND ($2::timestamptz IS NULL OR next_start >= $2)
|
|
AND ($3::timestamptz IS NULL OR seen_at <= $3)
|
|
ORDER BY seen_at
|
|
"""
|
|
|
|
|
|
async def capture_status(pool: asyncpg.Pool, account_id: int) -> CaptureStatus:
|
|
row = await pool.fetchrow(_STATUS, account_id)
|
|
if row is None:
|
|
return CaptureStatus(live=False, since=None, last_seen=None)
|
|
return CaptureStatus(
|
|
live=row["live"], since=row["started_at"], last_seen=row["seen_at"]
|
|
)
|
|
|
|
|
|
async def capture_gaps(
|
|
pool: asyncpg.Pool,
|
|
account_id: int,
|
|
*,
|
|
date_from: datetime | None = None,
|
|
date_to: datetime | None = None,
|
|
) -> list[CaptureGap]:
|
|
rows = await pool.fetch(_GAPS, account_id, date_from, date_to)
|
|
return [CaptureGap(**dict(row)) for row in rows]
|