Mykyta Savchuk (c3603be6) at 27 Mar 16:37
update NOTICE
Mykyta Savchuk (c3603be6) at 27 Mar 16:36
update NOTICE
@deshruch @deepapathak rebased
Mykyta Savchuk (8ca48cc7) at 27 Mar 13:32
add tests for empty nested data attributes
... and 1 more commit
Mykyta Savchuk (6aadc9d5) at 27 Mar 13:32
Mykyta Savchuk (8ca48cc7) at 27 Mar 12:56
add tests for empty nested data attributes
... and 3 more commits
Mykyta Savchuk (6aadc9d5) at 25 Mar 21:32
add tests for empty nested data attributes
Mykyta Savchuk (6aadc9d5) at 25 Mar 18:25
add tests for empty nested data attributes
Mykyta Savchuk (d4bb2933) at 22 Mar 16:19
handle null in nested attributes
fix NPE during indexing when one of the nested attributes in the array is null
Mykyta Savchuk (d4bb2933) at 22 Mar 16:12
handle null in nested attributes
The issue occurs in storage service when trying to update the same record (with the same id) using multiple asynchronous requests at the same time. As a result, only one version is saved in the database and the others are lost.
For example, suppose we call the storage PUT API with three asynchronous requests for the same record. Even though the storage returns 201 with version for each of the requests, calling /records/{id}/{version} with the three created versions results in two 404s and only one 200. All three versions are saved in the blob storage, but "gcsVersionPaths" array of the record in the database has only one new version.
Looking at the code, it appears that this is a lost update problem. When updating a record, the storage fetches the record from the database, performs certain manipulations on it, and then saves it in the database. So when multiple threads are running at the same time, they simultaneously fetch the same record (with the same "gcsVersionPaths" array), add a new version to the array, and save the record in the database. And each thread overwrites the newly added version by the previous thread, resulting in only one version being saved by the last thread executed.
Possible solution: Implement optimistic locking for PUT API. To implement optimistic locking, we can add an additional field to the database record that is updated together with the record. So we fetch the record along with this field and when saving it, we check whether the value of the field has changed, if so, we abort the changes. I'm assuming all provider databases have this functionality built in. For example, in Azure CosmosDB, every item stored in the database has a system-defined property "_etag", and to enable optimistic locking we can pass parameters when saving the record.
Mykyta Savchuk (aa1acdbf) at 03 Jan 14:35
add support more than 10 patch operations in a single request
Mykyta Savchuk (5de62f10) at 06 Dec 13:31
@chad could you please review the ADR too
The error appears to relate to line 174
a null pointer is being thrown when calling
subFieldParentElement.isJsonObject()
which leads to 500 error, so it looks like we need an extra null check on this property and to return null if it is before accessing.
Mykyta Savchuk (c8defb26) at 29 Jun 15:21
Mykyta Savchuk (6c55cf7c) at 29 Jun 13:12