Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions backend/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pathlib import Path
from datetime import datetime, timezone
from datetime import datetime, timezone, timedelta

import re
import os
Expand Down Expand Up @@ -363,7 +363,12 @@ def probe_page(request: Request, db: Session = Depends(get_db)):
"""

client_ip = _get_client_ip(request)
data = {"client_ip": client_ip, "test_target": "default"}
user_agent = request.headers.get("user-agent")
data = {
"client_ip": client_ip,
"user_agent": user_agent,
"test_target": "default",
}

ping_ms = _ping(client_ip)
if ping_ms is not None:
Expand Down Expand Up @@ -413,8 +418,27 @@ def probe_page(request: Request, db: Session = Depends(get_db)):
pass

data["asn"] = normalize_asn(data.get("asn"))
db_record = models.TestRecord(**data)
db.add(db_record)

ten_minutes_ago = datetime.utcnow() - timedelta(minutes=10)
existing = (
db.query(models.TestRecord)
.filter(
models.TestRecord.client_ip == client_ip,
models.TestRecord.user_agent == user_agent,
models.TestRecord.timestamp >= ten_minutes_ago,
)
.first()
)

if existing:
for key, value in data.items():
setattr(existing, key, value)
existing.timestamp = datetime.utcnow()
db_record = existing
else:
db_record = models.TestRecord(**data)
db.add(db_record)

db.commit()
db.refresh(db_record)

Expand All @@ -433,10 +457,10 @@ def api_root():

@app.get("/tests", response_model=schemas.TestsResponse)
def read_tests(request: Request, db: Session = Depends(get_db)):
"""Return recent test records for up to ten unique client IPs.
"""Return recent test records for up to ten client sessions.

Since each IP has at most one aggregated record, we simply return the ten
most recently updated rows.
Records are aggregated per client IP and user agent within the last ten
minutes, so we simply return the ten most recently updated rows.
"""

rows = (
Expand Down Expand Up @@ -464,7 +488,9 @@ def create_test(
):
data = record.dict()
client_ip = _get_client_ip(request)
user_agent = request.headers.get("user-agent")
data["client_ip"] = data.get("client_ip") or client_ip
data["user_agent"] = data.get("user_agent") or user_agent

if not data.get("location") or not data.get("asn") or not data.get("isp"):
try:
Expand Down Expand Up @@ -536,9 +562,14 @@ def create_test(
dl = data.pop("download_mbps", None)
ul = data.pop("upload_mbps", None)

ten_minutes_ago = datetime.utcnow() - timedelta(minutes=10)
existing = (
db.query(models.TestRecord)
.filter(models.TestRecord.client_ip == client_ip)
.filter(
models.TestRecord.client_ip == client_ip,
models.TestRecord.user_agent == user_agent,
models.TestRecord.timestamp >= ten_minutes_ago,
)
.first()
)

Expand Down Expand Up @@ -588,6 +619,7 @@ def _avg(a, b):

mapped = {
"client_ip": client_ip,
"user_agent": user_agent,
"location": data.get("location"),
"asn": data.get("asn"),
"isp": data.get("isp"),
Expand Down
1 change: 1 addition & 0 deletions backend/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class TestRecord(Base):
id = Column(Integer, primary_key=True, index=True)
timestamp = Column(DateTime, default=datetime.utcnow)
client_ip = Column(String)
user_agent = Column(String)
location = Column(String)
asn = Column(String)
isp = Column(String)
Expand Down
2 changes: 2 additions & 0 deletions backend/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class TestRecordBase(BaseModel):
client_ip: str | None = None
user_agent: str | None = None
location: str | None = None
asn: str | None = None
isp: str | None = None
Expand All @@ -26,6 +27,7 @@ class TestRecordBase(BaseModel):

class TestRecordCreate(BaseModel):
client_ip: str | None = None
user_agent: str | None = None
location: str | None = None
asn: str | None = None
isp: str | None = None
Expand Down
6 changes: 5 additions & 1 deletion backend/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ def test_create_test_merges_recent_records():
db.query(TestRecord).delete()
db.add(
TestRecord(
client_ip="testclient", ping_ms=10, ping_min_ms=8, ping_max_ms=12
client_ip="testclient",
user_agent="testclient",
ping_ms=10,
ping_min_ms=8,
ping_max_ms=12,
)
)
db.commit()
Expand Down