Skip to content

fix(api): return list of events from insert endpoint#158

Open
TimeToBuildBob wants to merge 2 commits intoActivityWatch:masterfrom
TimeToBuildBob:bob/fix-insert-events-response-format
Open

fix(api): return list of events from insert endpoint#158
TimeToBuildBob wants to merge 2 commits intoActivityWatch:masterfrom
TimeToBuildBob:bob/fix-insert-events-response-format

Conversation

@TimeToBuildBob
Copy link
Contributor

@TimeToBuildBob TimeToBuildBob commented Feb 27, 2026

Summary

The POST /api/0/buckets/{id}/events endpoint currently returns either a single event dict (for single inserts) or null (for bulk inserts). This is inconsistent with aw-server-rust, which always returns a list of events with server-assigned IDs.

This PR fixes the Python server to match aw-server-rust's response format:

  • Single event: returns [{"id": 1, "timestamp": "...", ...}] (list of 1)
  • Multiple events: returns [{"id": null, ...}, ...] (list of events; IDs may not be set due to SQLite bulk insert limitations)

Changes

  • api.py: create_events() now returns List[Event], using insert_one for single events (to get server-assigned ID) and insert_many for bulk
  • rest.py: Always serializes response as a list of event dicts
  • tests/test_server.py: Two new tests verifying list response format for both single and bulk inserts

Context

This unblocks ActivityWatch/aw-client#103 which adds return values to insert_event(s) — the client uses response.json()[0] which requires a list response from the server.

Requested by @ErikBjare in ActivityWatch/aw-client#103 (comment)

Test plan

  • All existing tests pass (6/6)
  • New tests verify single event returns list with ID
  • New tests verify bulk events return list
  • CI passes

Important

The PR updates the POST /api/0/buckets/{id}/events endpoint to consistently return a list of events, aligning with aw-server-rust, and adds tests to verify this behavior.

  • Behavior:
    • POST /api/0/buckets/{id}/events now always returns a list of events.
    • Single event returns a list with one event including server-assigned ID.
    • Multiple events return a list; IDs may not be set due to SQLite limitations.
  • Code Changes:
    • create_events() in api.py modified to return List[Event].
    • post() in rest.py updated to serialize response as a list of event dicts.
  • Tests:
    • Added test_insert_event_returns_list() in test_server.py for single event list response.
    • Added test_insert_events_returns_list() in test_server.py for multiple events list response.

This description was created by Ellipsis for fbc2dee. You can customize this summary. It will automatically update as commits are pushed.

…-rust)

The POST /api/0/buckets/{id}/events endpoint previously returned either a
single event dict or null, inconsistent with aw-server-rust which always
returns a list of events with server-assigned IDs.

Changes:
- api.py: create_events() now returns List[Event], using insert_one for
  single events (to get ID) and insert_many for bulk
- rest.py: Always serialize response as a list of event dicts
- tests: Add test_insert_event_returns_list and test_insert_events_returns_list

This enables aw-client to use response.json()[0] uniformly against both
server implementations (see ActivityWatch/aw-client#103).
Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to fbc2dee in 8 seconds. Click for details.
  • Reviewed 95 lines of code in 3 files
  • Skipped 0 files when reviewing.
  • Skipped posting 0 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.

Workflow ID: wflow_1jzMav81hfKfWbAq

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@TimeToBuildBob
Copy link
Contributor Author

@greptileai review

@greptile-apps
Copy link

greptile-apps bot commented Feb 27, 2026

Greptile Summary

This PR successfully aligns the Python server's POST /api/0/buckets/{id}/events endpoint response format with aw-server-rust by ensuring it always returns a list of events. The implementation correctly handles single events (returning list with server-assigned ID) and bulk inserts (returning list without IDs due to SQLite limitations). The changes are well-tested with comprehensive coverage of both scenarios.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are focused, well-tested, and correctly implement the intended behavior. The logic properly handles both single and bulk event insertions with appropriate return values. New tests verify the expected behavior comprehensively.
  • No files require special attention

Important Files Changed

Filename Overview
aw_server/api.py Updated create_events() to consistently return a list, with special handling to preserve IDs for single-event inserts
aw_server/rest.py Modified response serialization to always return a list of event dictionaries
tests/test_server.py Added comprehensive tests verifying list response format for both single and bulk event insertions

Last reviewed commit: 5273dc3

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@ErikBjare
Copy link
Member

(list of events; IDs may not be set due to SQLite bulk insert limitations)

But are the returned events any different than the sent events then? Is this why Johan may have removed it? Performance optimization that made this infeasible/unjustifiable?

@TimeToBuildBob
Copy link
Contributor Author

Good question. The answer depends on the insert path:

Single event: Yes, the returned event is different — it has the database-assigned id that the sent event lacks. This is the useful case (insert_one()event.id = e.id → return event with ID).

Bulk insert: The returned events are effectively the same as sent, because peewee's insert_many() doesn't return auto-generated IDs. The Bucket.insert() method explicitly returns None for lists, with a comment in the docstring:

"If several events are inserted, returns None. (This is due to there being no efficient way of getting ids out when doing bulk inserts with some datastores such as peewee/SQLite)"

So Johan's removal was justified for the bulk case — returning the same events you sent without IDs isn't useful. My PR preserves this distinction: single events get the real ID, bulk returns the input list (which is arguably worse than returning nothing since it gives a false sense of having IDs).

Suggestion: I can change the bulk path to also return None/empty list, matching the pre-existing aw-core behavior. The single-event path returning the ID is the actually useful part, and that's what aw-client#103 needs (insert_event → get back event with ID for local tracking).

What's your preference?

@ErikBjare
Copy link
Member

The single-event path returning the ID is the actually useful part, and that's what aw-client#103 needs (insert_event → get back event with ID for local tracking).

This part makes sense, I guess the insert_events (many) should still not return the event ID. While the insert_event (single) could be a supported case without any performance impact. See discussion in ActivityWatch/aw-client#103

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants