From 102f936156a60b29ffaba8c34287304ddcf4662f Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 29 Jul 2020 12:17:07 -0700 Subject: [PATCH] Rework into new person deleting service --- .../dao/expunge/ResourceExpungeService.java | 2 +- .../jpa/empi/config/EmpiConsumerConfig.java | 19 ++-- .../empi/svc/EmpiPersonDeletingSvcImpl.java | 87 +++++++++++++++ .../fhir/jpa/empi/svc/EmpiResetSvcImpl.java | 100 +++--------------- .../jpa/empi/svc/IEmpiPersonDeletingSvc.java | 10 ++ .../ca/uhn/fhir/empi/api/IEmpiResetSvc.java | 2 +- .../fhir/empi/provider/EmpiProviderDstu3.java | 2 +- .../fhir/empi/provider/EmpiProviderR4.java | 2 +- 8 files changed, 128 insertions(+), 96 deletions(-) create mode 100644 hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonDeletingSvcImpl.java create mode 100644 hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/IEmpiPersonDeletingSvc.java diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceExpungeService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceExpungeService.java index 7319d4a4a26..44b1148fa81 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceExpungeService.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceExpungeService.java @@ -67,7 +67,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @Service -class ResourceExpungeService implements IResourceExpungeService { +public class ResourceExpungeService implements IResourceExpungeService { private static final Logger ourLog = LoggerFactory.getLogger(ResourceExpungeService.class); @Autowired diff --git a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/config/EmpiConsumerConfig.java b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/config/EmpiConsumerConfig.java index 70ccb22ee85..fbcc2b0c312 100644 --- a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/config/EmpiConsumerConfig.java +++ b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/config/EmpiConsumerConfig.java @@ -22,13 +22,13 @@ package ca.uhn.fhir.jpa.empi.config; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.empi.api.IEmpiBatchService; -import ca.uhn.fhir.empi.api.IEmpiResetSvc; +import ca.uhn.fhir.empi.api.IEmpiChannelSubmitterSvc; import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc; import ca.uhn.fhir.empi.api.IEmpiLinkSvc; import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc; import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc; import ca.uhn.fhir.empi.api.IEmpiPersonMergerSvc; -import ca.uhn.fhir.empi.api.IEmpiChannelSubmitterSvc; +import ca.uhn.fhir.empi.api.IEmpiResetSvc; import ca.uhn.fhir.empi.api.IEmpiSettings; import ca.uhn.fhir.empi.log.Logs; import ca.uhn.fhir.empi.provider.EmpiProviderLoader; @@ -44,16 +44,18 @@ import ca.uhn.fhir.jpa.empi.dao.EmpiLinkFactory; import ca.uhn.fhir.jpa.empi.interceptor.EmpiStorageInterceptor; import ca.uhn.fhir.jpa.empi.interceptor.IEmpiStorageInterceptor; import ca.uhn.fhir.jpa.empi.svc.EmpiBatchSvcImpl; +import ca.uhn.fhir.jpa.empi.svc.EmpiChannelSubmitterSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiEidUpdateService; -import ca.uhn.fhir.jpa.empi.svc.EmpiResetSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiLinkQuerySvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiLinkSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiLinkUpdaterSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiMatchFinderSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiMatchLinkSvc; +import ca.uhn.fhir.jpa.empi.svc.EmpiPersonDeletingSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiPersonMergerSvcImpl; -import ca.uhn.fhir.jpa.empi.svc.EmpiChannelSubmitterSvcImpl; +import ca.uhn.fhir.jpa.empi.svc.EmpiResetSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiResourceDaoSvc; +import ca.uhn.fhir.jpa.empi.svc.IEmpiPersonDeletingSvc; import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiCandidateSearchCriteriaBuilderSvc; import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiCandidateSearchSvc; import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiPersonFindingSvc; @@ -180,8 +182,13 @@ public class EmpiConsumerConfig { } @Bean - IEmpiResetSvc empiResetSvc() { - return new EmpiResetSvcImpl(); + IEmpiResetSvc empiResetSvc(EmpiLinkDaoSvc theEmpiLinkDaoSvc, IEmpiPersonDeletingSvc theEmpiPersonDeletingSvcImpl ) { + return new EmpiResetSvcImpl(theEmpiLinkDaoSvc, theEmpiPersonDeletingSvcImpl); + } + + @Bean + IEmpiPersonDeletingSvc empiPersonDeletingSvc() { + return new EmpiPersonDeletingSvcImpl(); } @Bean diff --git a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonDeletingSvcImpl.java b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonDeletingSvcImpl.java new file mode 100644 index 00000000000..1141204a293 --- /dev/null +++ b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonDeletingSvcImpl.java @@ -0,0 +1,87 @@ +package ca.uhn.fhir.jpa.empi.svc; + +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.api.model.DeleteConflict; +import ca.uhn.fhir.jpa.api.model.DeleteConflictList; +import ca.uhn.fhir.jpa.api.model.ExpungeOptions; +import ca.uhn.fhir.jpa.dao.expunge.ExpungeService; +import ca.uhn.fhir.model.primitive.IdDt; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.IdType; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +import java.util.List; + +import static org.slf4j.LoggerFactory.getLogger; + +@Service +public class EmpiPersonDeletingSvcImpl implements IEmpiPersonDeletingSvc { + private static final Logger ourLog = getLogger(EmpiPersonDeletingSvcImpl.class); + + @Autowired + private DaoRegistry myDaoRegistry; + @Autowired + private ExpungeService myExpungeService; + @Autowired + private PlatformTransactionManager myPlatformTransactionManager; + + + /** + * Function which will delete all resources by their PIDs, and also delete any resources that were undeletable due to + * VersionConflictException + * @param theLongs + */ + @Override + public void deleteResourcesAndHandleConflicts(List theLongs) { + TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager); + txTemplate.execute((tx) ->{ + DeleteConflictList + deleteConflictList = new DeleteConflictList(); + theLongs.stream().forEach(pid -> deleteCascade(pid, deleteConflictList)); + + IFhirResourceDao personDao = myDaoRegistry.getResourceDao("Person"); + while (!deleteConflictList.isEmpty()) { + deleteConflictBatch(deleteConflictList, personDao); + } + return null; + }); + } + + /** + * Use the expunge service to expunge all historical and current versions of the resources associated to the PIDs. + */ + @Override + public void expungeHistoricalAndCurrentVersionsOfIds(List theLongs) { + ExpungeOptions options = new ExpungeOptions(); + options.setExpungeDeletedResources(true); + options.setExpungeOldVersions(true); + //myResourceExpungeService.expungeHistoricalVersionsOfIds(null, theLongs, new AtomicInteger(Integer.MAX_VALUE - 1)); + theLongs.stream() + .forEach(personId -> { + myExpungeService.expunge("Person", personId, null, options, null); + }); + //myResourceExpungeService.expungeCurrentVersionOfResources(null, theLongs, new AtomicInteger(Integer.MAX_VALUE - 1)); + } + + private void deleteCascade(Long pid, DeleteConflictList theDeleteConflictList) { + ourLog.debug("About to cascade delete: " + pid); + IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao("Person"); + resourceDao.delete(new IdType("Person/" + pid), theDeleteConflictList, null, null); + } + + private void deleteConflictBatch(DeleteConflictList theDcl, IFhirResourceDao theDao) { + DeleteConflictList newBatch = new DeleteConflictList(); + for (DeleteConflict next: theDcl) { + IdDt nextSource = next.getSourceId(); + ourLog.info("Have delete conflict {} - Cascading delete", next); + theDao.delete(nextSource.toVersionless(), newBatch, null, null); + } + theDcl.removeIf(x -> true); + theDcl.addAll(newBatch); + } +} diff --git a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiResetSvcImpl.java b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiResetSvcImpl.java index 11706d8810c..3c180a6e256 100644 --- a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiResetSvcImpl.java +++ b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiResetSvcImpl.java @@ -22,26 +22,14 @@ package ca.uhn.fhir.jpa.empi.svc; import ca.uhn.fhir.empi.api.IEmpiResetSvc; import ca.uhn.fhir.empi.util.EmpiUtil; -import ca.uhn.fhir.jpa.api.dao.DaoRegistry; -import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; -import ca.uhn.fhir.jpa.api.model.DeleteConflict; -import ca.uhn.fhir.jpa.api.model.DeleteConflictList; -import ca.uhn.fhir.jpa.dao.expunge.IResourceExpungeService; import ca.uhn.fhir.jpa.empi.dao.EmpiLinkDaoSvc; -import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.provider.ProviderConstants; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.r4.model.IdType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.support.TransactionTemplate; -import javax.annotation.PostConstruct; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; /** * This class is in charge of Clearing out existing EMPI links, as well as deleting all persons related to those EMPI Links. @@ -50,96 +38,36 @@ import java.util.concurrent.atomic.AtomicInteger; public class EmpiResetSvcImpl implements IEmpiResetSvc { private static final Logger ourLog = LoggerFactory.getLogger(EmpiResetSvcImpl.class); - @Autowired - EmpiLinkDaoSvc myEmpiLinkDaoSvc; - @Autowired - private IResourceExpungeService myResourceExpungeService; - @Autowired - private DaoRegistry myDaoRegistry; - @Autowired - private PlatformTransactionManager myTransactionManager; + final EmpiLinkDaoSvc myEmpiLinkDaoSvc; + final IEmpiPersonDeletingSvc myEmpiPersonDeletingSvcImpl; - private TransactionTemplate myTxTemplate; + @Autowired + public EmpiResetSvcImpl(EmpiLinkDaoSvc theEmpiLinkDaoSvc, IEmpiPersonDeletingSvc theEmpiPersonDeletingSvcImpl) { + myEmpiLinkDaoSvc = theEmpiLinkDaoSvc; + myEmpiPersonDeletingSvcImpl = theEmpiPersonDeletingSvcImpl; + } @Override public long expungeAllEmpiLinksOfTargetType(String theResourceType) { throwExceptionIfInvalidTargetType(theResourceType); List longs = myEmpiLinkDaoSvc.deleteAllEmpiLinksOfTypeAndReturnPersonPids(theResourceType); - deleteResourcesAndHandleConflicts(longs); - expungeHistoricalAndCurrentVersiondsOfIds(longs); + myEmpiPersonDeletingSvcImpl.deleteResourcesAndHandleConflicts(longs); + myEmpiPersonDeletingSvcImpl.expungeHistoricalAndCurrentVersionsOfIds(longs); return longs.size(); } - /** - * Function which will delete all resources by their PIDs, and also delete any resources that were undeletable due to - * VersionConflictException - * @param theLongs - */ - private void deleteResourcesAndHandleConflicts(List theLongs) { - DeleteConflictList - deleteConflictList = new DeleteConflictList(); - myTxTemplate.execute(tx -> { - theLongs.stream().forEach(pid -> deleteCascade(pid, deleteConflictList)); - return null; - }); - - IFhirResourceDao personDao = myDaoRegistry.getResourceDao("Person"); - while (!deleteConflictList.isEmpty()) { - myTxTemplate.execute(tx -> { - deleteConflictBatch(deleteConflictList, personDao); - return null; - }); - - } - } - private void throwExceptionIfInvalidTargetType(String theResourceType) { if (!EmpiUtil.supportedTargetType(theResourceType)) { throw new InvalidRequestException(ProviderConstants.EMPI_CLEAR + " does not support resource type: " + theResourceType); } } - @PostConstruct - public void start() { - myTxTemplate = new TransactionTemplate(myTransactionManager); - - } - - /** - * TODO GGG this operation likely won't scale very well. Consider adding slicing - */ @Override - public long expungeAllEmpiLinks() { - List longs = myEmpiLinkDaoSvc.deleteAllEmpiLinksAndReturnPersonPids(); - deleteResourcesAndHandleConflicts(longs); - expungeHistoricalAndCurrentVersiondsOfIds(longs); - return longs.size(); - } - - /** - * Use the expunge service to expunge all historical and current versions of the resources associated to the PIDs. - */ - private void expungeHistoricalAndCurrentVersiondsOfIds(List theLongs) { - myResourceExpungeService.expungeHistoricalVersionsOfIds(null, theLongs, new AtomicInteger(Integer.MAX_VALUE - 1)); - myResourceExpungeService.expungeCurrentVersionOfResources(null, theLongs, new AtomicInteger(Integer.MAX_VALUE - 1)); - } - - private void deleteConflictBatch(DeleteConflictList theDcl, IFhirResourceDao theDao) { - DeleteConflictList newBatch = new DeleteConflictList(); - for (DeleteConflict next: theDcl) { - IdDt nextSource = next.getSourceId(); - ourLog.info("Have delete conflict {} - Cascading delete", next); - theDao.delete(nextSource.toVersionless(), newBatch, null, null); - } - theDcl.removeIf(x -> true); - theDcl.addAll(newBatch); - } - - private void deleteCascade(Long pid, DeleteConflictList theDeleteConflictList) { - ourLog.debug("About to cascade delete: " + pid); - IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao("Person"); - myTxTemplate.executeWithoutResult((tx) -> resourceDao.delete(new IdType("Person/" + pid), theDeleteConflictList, null, null)); - + public long removeAllEmpiLinks() { + List personPids = myEmpiLinkDaoSvc.deleteAllEmpiLinksAndReturnPersonPids(); + myEmpiPersonDeletingSvcImpl.deleteResourcesAndHandleConflicts(personPids); + myEmpiPersonDeletingSvcImpl.expungeHistoricalAndCurrentVersionsOfIds(personPids); + return personPids.size(); } } diff --git a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/IEmpiPersonDeletingSvc.java b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/IEmpiPersonDeletingSvc.java new file mode 100644 index 00000000000..c893eb96281 --- /dev/null +++ b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/IEmpiPersonDeletingSvc.java @@ -0,0 +1,10 @@ +package ca.uhn.fhir.jpa.empi.svc; + +import java.util.List; + +public interface IEmpiPersonDeletingSvc { + + void deleteResourcesAndHandleConflicts(List theLongs); + + void expungeHistoricalAndCurrentVersionsOfIds(List theLongs); +} diff --git a/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/api/IEmpiResetSvc.java b/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/api/IEmpiResetSvc.java index 9afbb5188f5..d3ceafb773f 100644 --- a/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/api/IEmpiResetSvc.java +++ b/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/api/IEmpiResetSvc.java @@ -37,5 +37,5 @@ public interface IEmpiResetSvc { * * @return the count of deleted EMPI links */ - long expungeAllEmpiLinks(); + long removeAllEmpiLinks(); } diff --git a/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderDstu3.java b/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderDstu3.java index 1c30433a158..b428c0c0721 100644 --- a/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderDstu3.java +++ b/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderDstu3.java @@ -181,7 +181,7 @@ public class EmpiProviderDstu3 extends BaseEmpiProvider { public Parameters clearEmpiLinks(@OperationParam(name=ProviderConstants.EMPI_CLEAR_TARGET_TYPE, min = 0, max = 1) StringType theTargetType) { long resetCount; if (theTargetType == null || StringUtils.isBlank(theTargetType.getValue())) { - resetCount = myEmpiResetSvc.expungeAllEmpiLinks(); + resetCount = myEmpiResetSvc.removeAllEmpiLinks(); } else { resetCount = myEmpiResetSvc.expungeAllEmpiLinksOfTargetType(theTargetType.getValueNotNull()); } diff --git a/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderR4.java b/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderR4.java index 43b93ac2e69..31670b6ec41 100644 --- a/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderR4.java +++ b/hapi-fhir-server-empi/src/main/java/ca/uhn/fhir/empi/provider/EmpiProviderR4.java @@ -134,7 +134,7 @@ public class EmpiProviderR4 extends BaseEmpiProvider { public Parameters clearEmpiLinks(@OperationParam(name=ProviderConstants.EMPI_CLEAR_TARGET_TYPE, min = 0, max = 1) StringType theTargetType) { long resetCount; if (theTargetType == null || StringUtils.isBlank(theTargetType.getValue())) { - resetCount = myEmpiExpungeSvc.expungeAllEmpiLinks(); + resetCount = myEmpiExpungeSvc.removeAllEmpiLinks(); } else { resetCount = myEmpiExpungeSvc.expungeAllEmpiLinksOfTargetType(theTargetType.getValueNotNull()); }