PynamoDB icon indicating copy to clipboard operation
PynamoDB copied to clipboard

Exposing control over return_values in Model.update()

Open chkothe opened this issue 3 years ago • 2 comments

Problem

Currently, invoking .update() on a model will always read back the entire document from the DB with no option to override this behavior. If one's object is very large (e.g., contains long lists), one may not wish to receive everything (or anything at all) back after performing an update (e.g., in the common use case of a REST API handler). That's a use case for us at Intheon.

DynamoDB has of course a feature for that, the ReturnValues request parameter (which can take the values NONE, ALL_NEW, ALL_OLD, UPDATED_NEW and UPDATED_OLD), and that feature is already exposed in PynamoDB, but so far only in the low-level TableConnection.update_item() method. Unfortunately, falling back to that in user code would require the user to duplicate some internal PynamoDB logic and/or to invoke non-public methods of the model, so it's not really an alternative that can be recommended.

This PR

Currently, Model.update() simply hard-codes this value to ALL_NEW. This PR proposes to make that a new parameter instead, which can be overridden as in item.update(actions=[...], read_back=NONE) to read nothing back from the DB. At this time, the PR is trivial and permits only either ALL_NEW (default, and equivalent to the current behavior) or NONE, which reads nothing back and consequently returns None and leaves the local item unaltered.

I've pondered whether it should be called return_values instead, but that seems rather confusing to the user, who may assume that the flag affects only the return values of the update() method, while the local item might still be updated in-place as usual. Calling it read_back makes that clearer since it talks about what information comes back from the DB. That interpretation also holds up when in the future someone decides to add support for other DynamoDB modes like ALL_OLD, in which case we'd expect that the local copy will be populated with whatever the DB state was before the update happened (rather than only the return value receiving the old data).

While this PR is very simple, in the future someone could implement support for partial updates of the local record (via UPDATED_NEW), and this argument would allow the user to selectively choose one read-back mode or another, which would be an application-dependent choice (e.g., in the presence of concurrency), so there's some future-proofing in there.

A unit test that checks these semantics is provided.

chkothe avatar May 26 '22 00:05 chkothe

Sorry for overlooking this PR for so long. This is a very valid addition!

ikonst avatar Nov 05 '22 05:11 ikonst

I definitely should merge this before 6.x.

ikonst avatar Feb 06 '23 01:02 ikonst