Skip to content

Add play session ingest for game time tracking#3155

Open
tmgast wants to merge 3 commits intorommapp:masterfrom
tmgast:feature/play-session-ingest
Open

Add play session ingest for game time tracking#3155
tmgast wants to merge 3 commits intorommapp:masterfrom
tmgast:feature/play-session-ingest

Conversation

@tmgast
Copy link
Copy Markdown
Member

@tmgast tmgast commented Mar 22, 2026

Description

Adds play session tracking modeled after the Argosy session data format. Clients submit batches of play sessions per device, recording when and how long games were played. Sessions track both the time window (start_time/end_time) and screen-on time (duration_ms), which may differ due to device suspension or backgrounding.

Known Gaps

  • No frontend surface
  • No session editing or bulk delete

New Model

PlaySession

Field Type Description
id int (PK) Auto-incrementing ID
user_id int (FK) Owner, cascades on delete
device_id str? (FK) Device reference, SET NULL on device delete
rom_id int? (FK) ROM reference, SET NULL on ROM delete
save_slot str? Optional save slot name
start_time datetime When the session window began
end_time datetime When the session window ended
duration_ms bigint Screen-on time in milliseconds

Indexes: (user_id, rom_id), (user_id, start_time), unique on (user_id, device_id, rom_id, start_time)


New API Endpoints

POST /api/play-sessions

  • Batch ingest play sessions from a single device (max 100)
  • Unknown device_id or rom_id resolves to NULL rather than rejecting
  • Duplicates detected by (user_id, device_id, rom_id, start_time) via batched query
  • Updates rom_user.last_played and device.last_seen on success
REQUEST
{
  "device_id": "abc-123-uuid",
  "sessions": [
    {
      "rom_id": 42,
      "start_time": "2026-03-22T10:00:00Z",
      "end_time": "2026-03-22T10:30:00Z",
      "duration_ms": 1800000
    }
  ]
}

RESPONSE (201)
{
  "results": [
    {"index": 0, "status": "created", "id": 1}
  ],
  "created_count": 1,
  "skipped_count": 0
}

Per-item status is one of created, duplicate, or error.

GET /api/play-sessions

  • Query own sessions with optional filters
  • When start_after or end_before is set, the count limit is bypassed for stats use cases
Param Type Description
rom_id int? Filter by ROM
device_id str? Filter by device
start_after datetime? Sessions starting at or after this time
end_before datetime? Sessions starting at or before this time
limit int Page size (default 50, ignored when time range set)
offset int Pagination offset

DELETE /api/play-sessions/{session_id}

  • Delete own session (404 if not found or not owned)

Database Changes

  • Migration: 0073_play_sessions.py

AI Disclosure
Planning and review assisted by Claude Code

Checklist

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes (28 tests across 7 classes)

Backend API for collecting and querying play sessions, modeled after
the Argosy session data format. Clients submit batches per device,
recording both the session window and screen-on time.
Copilot AI review requested due to automatic review settings March 22, 2026 11:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds backend support for ingesting and querying per-user game play sessions (modeled after Argosy session data) to enable game-time tracking and “last played” updates.

Changes:

  • Introduces PlaySession model + Alembic migration with indexes for common query patterns and dedup identity.
  • Adds /api/play-sessions endpoints for batch ingest, querying, and delete; updates rom_user.last_played and device.last_seen.
  • Adds comprehensive endpoint tests covering ingest validation, dedup, isolation, and query filtering.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
backend/tests/endpoints/test_play_sessions.py New test suite covering ingest/query/delete behaviors and edge cases.
backend/tests/conftest.py Ensures PlaySession rows are cleared between tests.
backend/models/user.py Adds User.play_sessions relationship for cascading deletes/orphans.
backend/models/play_session.py New SQLAlchemy model for persisted play sessions with indexes/uniqueness.
backend/main.py Registers the new play-sessions router.
backend/handler/database/play_sessions_handler.py New DB handler for CRUD/query/dedup support.
backend/handler/database/init.py Exposes db_play_session_handler singleton.
backend/endpoints/responses/play_session.py Adds response/request schemas for play session APIs.
backend/endpoints/play_sessions.py Implements POST ingest (batch + dedup), GET query, DELETE by id.
backend/alembic/versions/0073_play_sessions.py Creates the play_sessions table and indexes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Replace per-item add_session with add_sessions using add_all.
No fallback on IntegrityError -- duplicate concurrent submissions
are the client's responsibility.
@gantoine gantoine added the on-hold Pending further research or blocked by another issue label Mar 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

on-hold Pending further research or blocked by another issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants