perf(api): fix n+1 query issue in user notification preferences update

- Added a benchmark script in tests/test_notifications_api.py that proved the N+1 issue issue.
- Replaced iterative DB lookups inside `for item in body.preferences:` with single pre-fetch query and local `prefs_dict` lookups.
- Verified test benchmark time drops from ~0.0964s to ~0.0141s for a batch of 100 items.

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot]
2026-03-16 09:20:41 +00:00
parent 2732dafba9
commit fe20e02f78
3 changed files with 110 additions and 10 deletions
+51
View File
@@ -830,3 +830,54 @@ class TestUserNotificationService:
result = _send_email_notification({"smtp_host": "smtp.example.com"}, "Title", "Body")
assert result is False
class TestBenchmark:
@pytest.mark.unit
def test_update_preferences_benchmark(self, notif_engine, notif_session):
import time
import statistics
from app.main import app
target = UserNotificationTarget(
owner_id=_OWNER,
channel_type="webhook",
name="My Webhook",
config=json.dumps({"url": "https://x.com"}),
)
notif_session.add(target)
notif_session.commit()
notif_session.refresh(target)
client = _make_client(notif_engine, _OWNER)
try:
items_count = 100
preferences = []
for i in range(items_count):
preferences.append({
"event_type": f"event.type.{i}",
"channel_type": "webhook",
"is_enabled": True,
"target_id": target.id,
})
payload = {"preferences": preferences}
# Warm up
client.put("/api/user-notifications/preferences", json=payload)
times = []
for _ in range(5):
# Alter the values a bit so it's a real update
for p in payload["preferences"]:
p["is_enabled"] = not p["is_enabled"]
start = time.time()
resp = client.put("/api/user-notifications/preferences", json=payload)
end = time.time()
assert resp.status_code == 200
times.append(end - start)
print(f"\nAverage time: {statistics.mean(times):.4f}s")
finally:
_cleanup(app)