0

I'm using the spring-cloud-gcp-starter-data-datastore dependency in a spring boot application to interface with a Datastore instance in GCP.

I have the following entity mapped out (condensed for brevity):

@Entity(name = "order_status")
public class OrderStatus {
    @Id
    @Field(name = "unique_key")
    private String uniqueKey;

    @Field(name = "order_id")
    private String orderId;

    @Field(name = "notification_preferences")
    private NotificationPreferences notificationPreferences;

    //lots of other fields + getters and setters
}

When an order event comes into my application, I save the order details in this entity in Datastore. At that time, the notificationPreferences field will be null.

The application also has an endpoint whose sole purpose is to update the notificationPreferences field for an order.

Both pieces of code make changes to the order_status entity in Datastore in the same way.

OrderStatus orderStatus = repo.findByOrderId(orderId);

//set fields

repo.save(orderStatus);

I'm having an intermittent issue when both an order status event and a notification preference update come in at the same time.

The order status event and notification preference update both read the OrderStatus from Datastore with the notification_preferences as null. The notification preference update code sets the notification_preferences value as it should, and then saves that to Datastore via the repo.save() call. However, the order status update event code still has notification_preferences set to null because it read that record from Datastore before the notification preference update finished. So, when the repo.save() method is called to update the order status, it sets the notification_preference field back to null.

So my question is, is there any way to exclude a field from being persisted so that when I call repo.save() from the order status update code it would never update the notification_preferences field?

Andrew Mairose
  • 10,615
  • 12
  • 60
  • 102

1 Answers1

0

Instead of trying to only update specific fields, you'll want to update the entire entity in each path, but you should use a transaction (https://cloud.spring.io/spring-cloud-static/Greenwich.RC2/multi/multi__spring_data_cloud_datastore.html#_transactions_2) in both cases. That way if there is a concurrent update one will fail, and you'll be able to retry the update attempt.

Jim Morrison
  • 2,784
  • 1
  • 7
  • 11