I have a custom entity which has near real-time updates (approx 1000 updates per minute). Since the same entity record could get updated in different batch update requests and the requests are received from different async sources, there are chances that a more recent update in the CDS could get overwritten by a slightly older update.
- Update-1 (with custom attribute datamodifiedon set to 8.02 PM) for Entity record A is processed by async service S1.
- Update-2 (with custom attribute datamodifiedon set to 8.03 PM) for Entity record A is processed by async service S2.
Due to network latency or some other reason, S1 service is slightly slow and service S2 went ahead and fired its update call for Entity record A with datamodifiedon 8.03 PM.
Service-1 now fires Update-1 on the same entity record and the update happened at 8.03PM gets overwritten by update happened at 8.02PM leading to data loss.
I have registered a plugin for my custom entity's Update SDK message at Stage 10(Pre-Validation). This plugin compares datamodifiedon attribute from input parameters with the one set in pre-entity images from plugin context. And throws Invalid Plugin Execution exception if the pre-entity image already has more recent datamodifiedon attribute.
// If ModifiedOn value in pre-image is later than the one received in input parameters, this is an obsolete request and must be rejected.
if (preImage.Contains("datamodifiedon")
&& preImage.GetAttributeValue<DateTime>("datamodifiedon") != DateTime.MinValue
&& entity.Contains("datamodifiedon")
&& entity.GetAttributeValue<DateTime>("datamodifiedon") != DateTime.MinValue
)
{
if (DateTime.Compare(preImage.GetAttributeValue<DateTime>("datamodifiedon"), entity.GetAttributeValue<DateTime>("datamodifiedon")) > 0)
{
string traceMessage = "PreOperationLiveWorkItemUpdatePlugin: Update request is obsolete. datamodifiedon field found in pre-entity image: "
+ preImage.GetAttributeValue<DateTime>("datamodifiedon")
+ "datamodifiedon field in Input parameters: "
+ entity.GetAttributeValue<DateTime>("datamodifiedon");
tracingService.Trace(traceMessage);
throw new InvalidPluginExecutionException(traceMessage);
}
}
Since the updates happen very frequently, is there a possibility that 1. Update-2 (datamodifiedon 8.03 PM) is in pre-validation stage. Post successful validation, actual update in database is in progress. 2. Now Update-1 enters pre-validation stage. Since Update-2 is not yet committed in the database, will the pre-entity image received in this stage be the old value still and lets the validation to go through?
Would registering this plugin at Pre-Operation or Post-Operation stage help instead of Pre-Validation stage since the other two stages execute in the same database transaction?
Is there any other way to solve this concurrency problem? Since the update is initiated via a batch odata call, eTag pre-condition cannot be used in the request header.