Rework into new person deleting service

This commit is contained in:
Tadgh 2020-07-29 12:17:07 -07:00
parent 0e88f359f5
commit 102f936156
8 changed files with 128 additions and 96 deletions

View File

@ -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

View File

@ -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

View File

@ -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<Long> 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<Long> 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<IBaseResource> 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);
}
}

View File

@ -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<Long> 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<Long> 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<Long> 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<Long> 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<IBaseResource> 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<Long> personPids = myEmpiLinkDaoSvc.deleteAllEmpiLinksAndReturnPersonPids();
myEmpiPersonDeletingSvcImpl.deleteResourcesAndHandleConflicts(personPids);
myEmpiPersonDeletingSvcImpl.expungeHistoricalAndCurrentVersionsOfIds(personPids);
return personPids.size();
}
}

View File

@ -0,0 +1,10 @@
package ca.uhn.fhir.jpa.empi.svc;
import java.util.List;
public interface IEmpiPersonDeletingSvc {
void deleteResourcesAndHandleConflicts(List<Long> theLongs);
void expungeHistoricalAndCurrentVersionsOfIds(List<Long> theLongs);
}

View File

@ -37,5 +37,5 @@ public interface IEmpiResetSvc {
*
* @return the count of deleted EMPI links
*/
long expungeAllEmpiLinks();
long removeAllEmpiLinks();
}

View File

@ -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());
}

View File

@ -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());
}