Skip to content

FEATURE: Optimise Save endpoint: replace fetch-append-$set with atomic $push operator #38

Description

@DewaldOosthuizen

Summary

The Save.post() handler fetches the full messages list, appends the new message in Python, then writes the entire array back with $set. Under concurrent requests this is a read-modify-write race: two simultaneous saves can both read the same list, each append their message, and the second write silently overwrites the first save.

Background

MongoDB provides the $push operator specifically to atomically append to an array field without a read-modify-write cycle. Using it eliminates the race condition, removes the unnecessary get_user_messages() call, and reduces the operation from two round-trips (find + update) to one.

Affected Areas

  • web/app.pySave.post() (lines 141–160)
  • web/tests/test_app.pytest_save_valid_token_saves_and_returns_200 (mock setup needs adjustment)

Recommended Fix

def post(self):
    data = request.get_json(silent=True, force=True)
    if not data:
        return {"status": 400, "msg": "Request body must be valid JSON"}, 400
    message = data.get("message")
    if not message:
        return {"status": 400, "msg": "message is required"}, 400
    users.update_one(
        {"Username": request.username},
        {"$push": {"Messages": message}}
    )
    return {"status": 200, "msg": "Message has been saved successfully"}, 200

Acceptance Criteria

  • Save.post() uses a single update_one with $push — no prior find call
  • get_user_messages() is no longer called from Save.post()
  • All existing Save tests updated and passing
  • A concurrency test or comment documents the fix rationale

Complexity Estimate

S — simple code change with test updates; merits a concurrency note in documentation.

Priority

Medium — race condition is real but only observable under concurrent load.


Auto-identified by workspace issue-logger
Category: code optimisation / performance
Complexity: S
Repository: DewaldOosthuizen/python_rest_tutorial

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpythonPull requests that update python code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions