Wrapping $meta-add and $meta-delete operation in transactionService execution to support partitioning (#6082)

* wrapping metaAdd/Delete operation in transactionService.execute to have the tenant acknowledged by Spring.

* spotless happiness.

* fixing broken test.

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>
This commit is contained in:
Etienne Poirier 2024-07-08 07:33:02 -04:00 committed by GitHub
parent ecef72729f
commit aafa445d19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 56 additions and 19 deletions

View File

@ -1027,19 +1027,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
List<TagDefinition> tags = toTagList(theMetaAdd);
for (TagDefinition nextDef : tags) {
boolean hasTag = false;
boolean entityHasTag = false;
for (BaseTag next : new ArrayList<>(theEntity.getTags())) {
if (Objects.equals(next.getTag().getTagType(), nextDef.getTagType())
&& Objects.equals(next.getTag().getSystem(), nextDef.getSystem())
&& Objects.equals(next.getTag().getCode(), nextDef.getCode())
&& Objects.equals(next.getTag().getVersion(), nextDef.getVersion())
&& Objects.equals(next.getTag().getUserSelected(), nextDef.getUserSelected())) {
hasTag = true;
entityHasTag = true;
break;
}
}
if (!hasTag) {
if (!entityHasTag) {
theEntity.setHasTags(true);
TagDefinition def = getTagOrNull(
@ -1351,15 +1351,33 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Transactional
public <MT extends IBaseMetaType> MT metaAddOperation(
IIdType theResourceId, MT theMetaAdd, RequestDetails theRequest) {
RequestPartitionId requestPartitionId =
myRequestPartitionHelperService.determineReadPartitionForRequestForServerOperation(
theRequest, JpaConstants.OPERATION_META_ADD);
myTransactionService
.withRequest(theRequest)
.withRequestPartitionId(requestPartitionId)
.execute(() -> doMetaAddOperation(theResourceId, theMetaAdd, theRequest, requestPartitionId));
@SuppressWarnings("unchecked")
MT retVal = (MT) metaGetOperation(theMetaAdd.getClass(), theResourceId, theRequest);
return retVal;
}
protected <MT extends IBaseMetaType> void doMetaAddOperation(
IIdType theResourceId, MT theMetaAdd, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {
TransactionDetails transactionDetails = new TransactionDetails();
StopWatch w = new StopWatch();
BaseHasResource entity = readEntity(theResourceId, theRequest);
if (entity == null) {
BaseHasResource entity = readEntity(theResourceId, true, theRequest, theRequestPartitionId);
if (isNull(entity)) {
throw new ResourceNotFoundException(Msg.code(1993) + theResourceId);
}
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequest, transactionDetails);
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequestPartitionId, transactionDetails);
if (latestVersion.getVersion() != entity.getVersion()) {
doMetaAdd(theMetaAdd, entity, theRequest, transactionDetails);
} else {
@ -1372,27 +1390,43 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
ourLog.debug("Processed metaAddOperation on {} in {}ms", theResourceId, w.getMillisAndRestart());
@SuppressWarnings("unchecked")
MT retVal = (MT) metaGetOperation(theMetaAdd.getClass(), theResourceId, theRequest);
return retVal;
}
@Override
@Transactional
public <MT extends IBaseMetaType> MT metaDeleteOperation(
IIdType theResourceId, MT theMetaDel, RequestDetails theRequest) {
TransactionDetails transactionDetails = new TransactionDetails();
RequestPartitionId requestPartitionId =
myRequestPartitionHelperService.determineReadPartitionForRequestForServerOperation(
theRequest, JpaConstants.OPERATION_META_DELETE);
myTransactionService
.withRequest(theRequest)
.withRequestPartitionId(requestPartitionId)
.execute(() -> doMetaDeleteOperation(theResourceId, theMetaDel, theRequest, requestPartitionId));
@SuppressWarnings("unchecked")
MT retVal = (MT) metaGetOperation(theMetaDel.getClass(), theResourceId, theRequest);
return retVal;
}
@Transactional
public <MT extends IBaseMetaType> void doMetaDeleteOperation(
IIdType theResourceId, MT theMetaDel, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {
TransactionDetails transactionDetails = new TransactionDetails();
StopWatch w = new StopWatch();
BaseHasResource entity = readEntity(theResourceId, theRequest);
if (entity == null) {
BaseHasResource entity = readEntity(theResourceId, true, theRequest, theRequestPartitionId);
if (isNull(entity)) {
throw new ResourceNotFoundException(Msg.code(1994) + theResourceId);
}
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequest, transactionDetails);
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequestPartitionId, transactionDetails);
boolean nonVersionedTags =
myStorageSettings.getTagStorageMode() != JpaStorageSettings.TagStorageModeEnum.VERSIONED;
if (latestVersion.getVersion() != entity.getVersion() || nonVersionedTags) {
doMetaDelete(theMetaDel, entity, theRequest, transactionDetails);
} else {
@ -1404,10 +1438,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
ourLog.debug("Processed metaDeleteOperation on {} in {}ms", theResourceId.getValue(), w.getMillisAndRestart());
@SuppressWarnings("unchecked")
MT retVal = (MT) metaGetOperation(theMetaDel.getClass(), theResourceId, theRequest);
return retVal;
}
@Override
@ -1825,7 +1855,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
IIdType theId, RequestDetails theRequestDetails, TransactionDetails theTransactionDetails) {
RequestPartitionId requestPartitionId = myRequestPartitionHelperService.determineReadPartitionForRequestForRead(
theRequestDetails, getResourceName(), theId);
return readEntityLatestVersion(theId, requestPartitionId, theTransactionDetails);
return myTransactionService
.withRequest(theRequestDetails)
.withRequestPartitionId(requestPartitionId)
.execute(() -> readEntityLatestVersion(theId, requestPartitionId, theTransactionDetails));
}
@Nonnull

View File

@ -232,6 +232,9 @@ class BaseHapiFhirResourceDaoTest {
entity.setId(123L);
entity.setFhirId("456");
// set a transactionService that will actually execute the callback
mySvc.setTransactionService(new MockHapiTransactionService());
// mock
when(myRequestPartitionHelperSvc.determineReadPartitionForRequestForRead(
any(RequestDetails.class),