Skip to content

fix(api): return inserted event with server-assigned ID from single insert; return [] from bulk - #158

Merged
ErikBjare merged 4 commits into
ActivityWatch:masterfrom
TimeToBuildBob:bob/fix-insert-events-response-format
Jul 22, 2026
Merged

fix(api): return inserted event with server-assigned ID from single insert; return [] from bulk#158
ErikBjare merged 4 commits into
ActivityWatch:masterfrom
TimeToBuildBob:bob/fix-insert-events-response-format

Conversation

@TimeToBuildBob

@TimeToBuildBob TimeToBuildBob commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

What and why

POST /api/0/buckets/{id}/events previously returned inconsistent responses:

  • single event → bare event dict (no list wrapping)
  • bulk events → null

This mismatches aw-server-rust (which always returns a list) and blocked aw-client from
surfacing server-assigned event IDs to callers (ActivityWatch/aw-client#103).

This PR fixes the Python server response format:

Case Before After
Single event {...} (dict, no ID guarantee) [{"id": 1, ...}] (list with server-assigned ID)
Bulk events null [] (empty list — SQLite bulk insert can't return IDs efficiently)

The single-event path uses insert_one() which does return the assigned ID;
the bulk path returns an empty list rather than the input events (which would be
misleading since they lack IDs).

Changes

  • api.py: create_events() returns List[Event]insert_one for single (gets ID), insert_many for bulk (returns [])
  • rest.py: serializes response as a list of event dicts
  • tests/test_server.py: two new tests verifying list response for single and bulk inserts

Unblocks

ActivityWatch/aw-client#103 — which adds insert_event()Optional[Event] return value
so callers can retrieve the server-assigned ID for subsequent update/delete.

@ellipsis-dev ellipsis-dev Bot left a comment

Copy link
Copy Markdown

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
Copy Markdown
Contributor Author

@greptileai review

@greptile-apps

greptile-apps Bot commented Feb 27, 2026

Copy link
Copy Markdown

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

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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

@ErikBjare

Copy link
Copy Markdown
Member

@TimeToBuildBob See my comment #158 (comment)

…-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).
…edback)

Previously returned the same events without IDs, which gave false sense of having IDs.
@TimeToBuildBob
TimeToBuildBob force-pushed the bob/fix-insert-events-response-format branch from 5273dc3 to 73dfafe Compare June 29, 2026 13:11
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Updated per your comment: bulk insert now returns [] instead of the input events without IDs. Single-event insert still returns the event with the server-assigned ID. Rebased onto latest master.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

The only failing CI check is format — black wants the closing """ of the create_events() docstring in api.py to be on its own line. All tests, lint, and typecheck pass.

I've held off pushing the fix autonomously given the AW PR policy, but it's a one-liner when you're ready:

# current (black dislikes):
        For bulk inserts, returns empty list (events may not have IDs without a response-SQL roundtrip)."""

# needed:
        For bulk inserts, returns empty list (events may not have IDs without a response-SQL roundtrip).
        """

Let me know if you'd like me to push it.

@ErikBjare

Copy link
Copy Markdown
Member

@TimeToBuildBob Address the failing CI and rename the PR title+desc to reflect what it does and why. Also see/deal with/ping with context on ActivityWatch/aw-client#103

@TimeToBuildBob TimeToBuildBob changed the title fix(api): return list of events from insert endpoint fix(api): return inserted event with server-assigned ID from single insert; return [] from bulk Jul 22, 2026
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Done:

  • CI fixed: pushed style: move closing docstring quote to its own line (black) — the only failing check was black wanting the closing """ on its own line. Should be green now.
  • Title + description updated: now leads with the what/why — single insert returns event with server-assigned ID, bulk returns [].
  • aw-client#103: added a status comment there linking back. The relevant context: bulk insert returns [] (not the input events), so insert_events() on the client side should expect Optional[List[Event]] that may be empty for bulk. Single-event insert_event() gets back the event with its ID, which is the useful case.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click.

This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted.

@ErikBjare
ErikBjare merged commit 481c9a9 into ActivityWatch:master Jul 22, 2026
6 checks passed
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