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.py — Save.post() (lines 141–160)
web/tests/test_app.py — test_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
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
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
$pushoperator specifically to atomically append to an array field without a read-modify-write cycle. Using it eliminates the race condition, removes the unnecessaryget_user_messages()call, and reduces the operation from two round-trips (find + update) to one.Affected Areas
web/app.py—Save.post()(lines 141–160)web/tests/test_app.py—test_save_valid_token_saves_and_returns_200(mock setup needs adjustment)Recommended Fix
Acceptance Criteria
Save.post()uses a singleupdate_onewith$push— no priorfindcallget_user_messages()is no longer called fromSave.post()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