From 5e05703c1a5053ed7db800499edd6c8833aa6f89 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Tue, 9 Jul 2019 10:58:57 -0400 Subject: [PATCH 1/5] Add expunge-everything hook. Also add RequestDetails to all expunge operations --- .../ca/uhn/fhir/interceptor/api/Pointcut.java | 9 ++++++++ .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 8 +++---- .../fhir/jpa/dao/BaseHapiFhirSystemDao.java | 4 ++-- .../ca/uhn/fhir/jpa/dao/IFhirResourceDao.java | 3 +-- .../ca/uhn/fhir/jpa/dao/IFhirSystemDao.java | 2 +- .../dao/expunge/ExpungeEverythingService.java | 21 ++++++++++++++++++- .../uhn/fhir/jpa/dao/expunge/ExpungeRun.java | 5 ++++- .../fhir/jpa/dao/expunge/ExpungeService.java | 9 ++++---- .../jpa/provider/BaseJpaResourceProvider.java | 2 +- .../jpa/provider/BaseJpaSystemProvider.java | 4 ++-- .../jpa/provider/JpaSystemProviderDstu2.java | 10 +++++---- .../dstu3/JpaSystemProviderDstu3.java | 10 +++++---- .../jpa/provider/r4/JpaSystemProviderR4.java | 10 +++++---- .../java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java | 2 +- .../ResourceProviderExpungeDstu2Test.java | 10 ++++----- .../ResourceProviderExpungeDstu3Test.java | 12 +++++------ .../fhir/jpa/provider/r4/ExpungeR4Test.java | 16 +++++++------- 17 files changed, 87 insertions(+), 50 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 01d2e5637e4..01c0ad57639 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -1124,6 +1124,15 @@ public enum Pointcut { "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails" ), + STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING( + // Return type + Void.class, + // Params + "java.util.concurrent.atomic.AtomicInteger", + "ca.uhn.fhir.rest.api.server.RequestDetails", + "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails" + ), + /** * Note that this is a performance tracing hook. Use with caution in production * systems, since calling it may (or may not) carry a cost. diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 3172a0d5626..e2764594130 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -555,18 +555,18 @@ public abstract class BaseHapiFhirResourceDao extends B throw new PreconditionFailedException("Can not perform version-specific expunge of resource " + theId.toUnqualified().getValue() + " as this is the current version"); } - return myExpungeService.expunge(getResourceName(), entity.getResourceId(), entity.getVersion(), theExpungeOptions); + return myExpungeService.expunge(getResourceName(), entity.getResourceId(), entity.getVersion(), theExpungeOptions, theRequest); } - return myExpungeService.expunge(getResourceName(), entity.getResourceId(), null, theExpungeOptions); + return myExpungeService.expunge(getResourceName(), entity.getResourceId(), null, theExpungeOptions ,theRequest); } @Override @Transactional(propagation = Propagation.NEVER) - public ExpungeOutcome expunge(ExpungeOptions theExpungeOptions) { + public ExpungeOutcome expunge(ExpungeOptions theExpungeOptions, RequestDetails theRequestDetails) { ourLog.info("Beginning TYPE[{}] expunge operation", getResourceName()); - return myExpungeService.expunge(getResourceName(), null, null, theExpungeOptions); + return myExpungeService.expunge(getResourceName(), null, null, theExpungeOptions, theRequestDetails); } public String getResourceName() { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java index 3a535cd9533..e5842df1d8c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java @@ -49,8 +49,8 @@ public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDao extends IDao { */ DeleteMethodOutcome deleteByUrl(String theString, RequestDetails theRequestDetails); - ExpungeOutcome expunge(ExpungeOptions theExpungeOptions); + ExpungeOutcome expunge(ExpungeOptions theExpungeOptions, RequestDetails theRequestDetails); ExpungeOutcome expunge(IIdType theIIdType, ExpungeOptions theExpungeOptions, RequestDetails theRequest); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java index 0590b4a861a..ca1dec6d07d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java @@ -37,7 +37,7 @@ import java.util.Map; */ public interface IFhirSystemDao extends IDao { - ExpungeOutcome expunge(ExpungeOptions theExpungeOptions); + ExpungeOutcome expunge(ExpungeOptions theExpungeOptions, RequestDetails theRequestDetails); @SuppressWarnings("unchecked") IFhirResourceDao getDao(Class theType); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java index b704bb0668e..25cd6487ce0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java @@ -20,8 +20,16 @@ package ca.uhn.fhir.jpa.dao.expunge; * #L% */ +import ca.uhn.fhir.interceptor.api.HookParams; +import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; +import ca.uhn.fhir.interceptor.api.Pointcut; +import ca.uhn.fhir.jpa.delete.DeleteConflictList; +import ca.uhn.fhir.jpa.delete.DeleteConflictOutcome; import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.model.entity.*; +import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.StopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,13 +53,24 @@ public class ExpungeEverythingService { private static final Logger ourLog = LoggerFactory.getLogger(ExpungeEverythingService.class); @PersistenceContext(type = PersistenceContextType.TRANSACTION) protected EntityManager myEntityManager; + // FIXME KHS remove? @Autowired private PlatformTransactionManager myPlatformTransactionManager; + @Autowired + protected IInterceptorBroadcaster myInterceptorBroadcaster; - void expungeEverything() { + void expungeEverything(RequestDetails theRequest) { final AtomicInteger counter = new AtomicInteger(); + // Notify Interceptors about pre-action call + HookParams hooks = new HookParams() + .add(AtomicInteger.class, counter) + .add(RequestDetails.class, theRequest) + .addIfMatchesType(ServletRequestDetails.class, theRequest); + JpaInterceptorBroadcaster.doCallHooksAndReturnObject(myInterceptorBroadcaster, theRequest, Pointcut.STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING, hooks); + + ourLog.info("BEGINNING GLOBAL $expunge"); TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeRun.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeRun.java index 2efa285fe75..018645b9d09 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeRun.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeRun.java @@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao.expunge; import ca.uhn.fhir.jpa.util.ExpungeOptions; import ca.uhn.fhir.jpa.util.ExpungeOutcome; +import ca.uhn.fhir.rest.api.server.RequestDetails; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -49,13 +50,15 @@ public class ExpungeRun implements Callable { private final Long myResourceId; private final Long myVersion; private final ExpungeOptions myExpungeOptions; + private final RequestDetails myRequestDetails; private final AtomicInteger myRemainingCount; - public ExpungeRun(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions) { + public ExpungeRun(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions, RequestDetails theRequestDetails) { myResourceName = theResourceName; myResourceId = theResourceId; myVersion = theVersion; myExpungeOptions = theExpungeOptions; + myRequestDetails = theRequestDetails; myRemainingCount = new AtomicInteger(myExpungeOptions.getLimit()); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeService.java index b38dc77c7a7..0f4ff4e7be2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeService.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeService.java @@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.dao.expunge; import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.util.ExpungeOptions; import ca.uhn.fhir.jpa.util.ExpungeOutcome; +import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import org.slf4j.Logger; @@ -43,9 +44,9 @@ public abstract class ExpungeService { private IResourceExpungeService myExpungeDaoService; @Lookup - protected abstract ExpungeRun getExpungeRun(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions); + protected abstract ExpungeRun getExpungeRun(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions, RequestDetails theRequestDetails); - public ExpungeOutcome expunge(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions) { + public ExpungeOutcome expunge(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions, RequestDetails theRequest) { ourLog.info("Expunge: ResourceName[{}] Id[{}] Version[{}] Options[{}]", theResourceName, theResourceId, theVersion, theExpungeOptions); if (!myConfig.isExpungeEnabled()) { @@ -58,11 +59,11 @@ public abstract class ExpungeService { if (theResourceName == null && theResourceId == null && theVersion == null) { if (theExpungeOptions.isExpungeEverything()) { - myExpungeEverythingService.expungeEverything(); + myExpungeEverythingService.expungeEverything(theRequest); } } - ExpungeRun expungeRun = getExpungeRun(theResourceName, theResourceId, theVersion, theExpungeOptions); + ExpungeRun expungeRun = getExpungeRun(theResourceName, theResourceId, theVersion, theExpungeOptions, theRequest); return expungeRun.call(); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProvider.java index f77beb9ced6..078fc7d5878 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProvider.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProvider.java @@ -62,7 +62,7 @@ public abstract class BaseJpaResourceProvider extends B if (theIdParam != null) { outcome = getDao().expunge(theIdParam, options, theRequest); } else { - outcome = getDao().expunge(options); + outcome = getDao().expunge(options, theRequest); } return createExpungeResponse(outcome); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java index 9bfc3a1cd86..2be9cbb1862 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java @@ -55,9 +55,9 @@ public class BaseJpaSystemProvider extends BaseJpaProvider implements IJp return myResourceReindexingSvc; } - protected Parameters doExpunge(IPrimitiveType theLimit, IPrimitiveType theExpungeDeletedResources, IPrimitiveType theExpungeOldVersions, IPrimitiveType theExpungeEverything) { + protected Parameters doExpunge(IPrimitiveType theLimit, IPrimitiveType theExpungeDeletedResources, IPrimitiveType theExpungeOldVersions, IPrimitiveType theExpungeEverything, RequestDetails theRequestDetails) { ExpungeOptions options = createExpungeOptions(theLimit, theExpungeDeletedResources, theExpungeOldVersions, theExpungeEverything); - ExpungeOutcome outcome = getDao().expunge(options); + ExpungeOutcome outcome = getDao().expunge(options, theRequestDetails); return createExpungeResponse(outcome); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java index 6d3e40bbc9a..1f6f096dd4b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java @@ -71,9 +71,10 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus= 3) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderExpungeDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderExpungeDstu2Test.java index 882aa8aabfd..1e2e511427d 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderExpungeDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderExpungeDstu2Test.java @@ -194,7 +194,7 @@ public class ResourceProviderExpungeDstu2Test extends BaseResourceProviderDstu2T @Test public void testExpungeSystemEverything() { mySystemDao.expunge(new ExpungeOptions() - .setExpungeEverything(true)); + .setExpungeEverything(true), null); // Everything deleted assertExpunged(myOneVersionPatientId); @@ -214,7 +214,7 @@ public class ResourceProviderExpungeDstu2Test extends BaseResourceProviderDstu2T public void testExpungeSystemOldVersionsAndDeleted() { mySystemDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -233,7 +233,7 @@ public class ResourceProviderExpungeDstu2Test extends BaseResourceProviderDstu2T public void testExpungeTypeDeletedResources() { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(false)); + .setExpungeOldVersions(false), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -252,7 +252,7 @@ public class ResourceProviderExpungeDstu2Test extends BaseResourceProviderDstu2T public void testExpungeTypeOldVersions() { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(false) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -272,7 +272,7 @@ public class ResourceProviderExpungeDstu2Test extends BaseResourceProviderDstu2T public void testExpungeTypeOldVersionsAndDeleted() { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderExpungeDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderExpungeDstu3Test.java index c9421bf36ca..e81000616b4 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderExpungeDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderExpungeDstu3Test.java @@ -199,7 +199,7 @@ public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3T @Test public void testExpungeSystemEverything() { mySystemDao.expunge(new ExpungeOptions() - .setExpungeEverything(true)); + .setExpungeEverything(true), null); // Everything deleted assertExpunged(myOneVersionPatientId); @@ -219,7 +219,7 @@ public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3T public void testExpungeSystemOldVersionsAndDeleted() { mySystemDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -238,7 +238,7 @@ public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3T public void testExpungeTypeDeletedResources() { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(false)); + .setExpungeOldVersions(false), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -257,7 +257,7 @@ public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3T public void testExpungeTypeOldVersions() { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(false) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -277,7 +277,7 @@ public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3T public void testExpungeTypeOldVersionsAndDeleted() { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -298,7 +298,7 @@ public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3T myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) .setExpungeOldVersions(true) - .setLimit(0)); + .setLimit(0), null); fail(); } catch (InvalidRequestException e) { assertEquals("Expunge limit may not be less than 1. Received expunge limit 0.", e.getMessage()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java index 89dbb655c23..6d1654cd9f0 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java @@ -177,7 +177,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); runInTransaction(() -> assertThat(myResourceTableDao.findAll(), empty())); runInTransaction(() -> assertThat(myResourceHistoryTableDao.findAll(), empty())); @@ -234,7 +234,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { mySystemDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -255,7 +255,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(false)); + .setExpungeOldVersions(false), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -276,7 +276,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(false) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -297,7 +297,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { createStandardPatients(); mySystemDao.expunge(new ExpungeOptions() - .setExpungeEverything(true)); + .setExpungeEverything(true), null); // Everything deleted assertExpunged(myOneVersionPatientId); @@ -319,7 +319,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { myPatientDao.expunge(new ExpungeOptions() .setExpungeDeletedResources(true) - .setExpungeOldVersions(true)); + .setExpungeOldVersions(true), null); // Only deleted and prior patients assertStillThere(myOneVersionPatientId); @@ -349,7 +349,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { }); mySystemDao.expunge(new ExpungeOptions() - .setExpungeEverything(true)); + .setExpungeEverything(true), null); // Everything deleted assertExpunged(myOneVersionPatientId); @@ -380,7 +380,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { mySystemDao.expunge(new ExpungeOptions() - .setExpungeDeletedResources(true)); + .setExpungeDeletedResources(true), null); // Everything deleted assertExpunged(myOneVersionPatientId); From 7aaa75c2556bf02195e12aa8e113504b99a84cfb Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 10 Jul 2019 10:09:43 -0400 Subject: [PATCH 2/5] fixed pointcut --- .../ca/uhn/fhir/interceptor/api/Pointcut.java | 2 +- .../dao/expunge/ExpungeEverythingService.java | 85 ++++++++++--------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 01c0ad57639..36ac1cd73b8 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -1126,7 +1126,7 @@ public enum Pointcut { STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING( // Return type - Void.class, + void.class, // Params "java.util.concurrent.atomic.AtomicInteger", "ca.uhn.fhir.rest.api.server.RequestDetails", diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java index 25cd6487ce0..52824982c38 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ExpungeEverythingService.java @@ -23,8 +23,6 @@ package ca.uhn.fhir.jpa.dao.expunge; import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.Pointcut; -import ca.uhn.fhir.jpa.delete.DeleteConflictList; -import ca.uhn.fhir.jpa.delete.DeleteConflictOutcome; import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster; @@ -39,6 +37,7 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.support.TransactionTemplate; +import javax.annotation.PostConstruct; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContextType; @@ -53,12 +52,18 @@ public class ExpungeEverythingService { private static final Logger ourLog = LoggerFactory.getLogger(ExpungeEverythingService.class); @PersistenceContext(type = PersistenceContextType.TRANSACTION) protected EntityManager myEntityManager; - // FIXME KHS remove? @Autowired private PlatformTransactionManager myPlatformTransactionManager; @Autowired protected IInterceptorBroadcaster myInterceptorBroadcaster; + private TransactionTemplate myTxTemplate; + + @PostConstruct + public void initTxTemplate() { + myTxTemplate = new TransactionTemplate(myPlatformTransactionManager); + } + void expungeEverything(RequestDetails theRequest) { final AtomicInteger counter = new AtomicInteger(); @@ -68,55 +73,53 @@ public class ExpungeEverythingService { .add(AtomicInteger.class, counter) .add(RequestDetails.class, theRequest) .addIfMatchesType(ServletRequestDetails.class, theRequest); - JpaInterceptorBroadcaster.doCallHooksAndReturnObject(myInterceptorBroadcaster, theRequest, Pointcut.STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING, hooks); - + JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING, hooks); ourLog.info("BEGINNING GLOBAL $expunge"); - TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager); - txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); - txTemplate.execute(t -> { + myTxTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + myTxTemplate.execute(t -> { counter.addAndGet(doExpungeEverythingQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null")); counter.addAndGet(doExpungeEverythingQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null")); counter.addAndGet(doExpungeEverythingQuery("UPDATE " + TermCodeSystem.class.getSimpleName() + " d SET d.myCurrentVersion = null")); return null; }); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, SearchParamPresent.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ForcedId.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedSearchParamDate.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedSearchParamNumber.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedSearchParamQuantity.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedSearchParamString.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedSearchParamToken.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedSearchParamUri.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedSearchParamCoords.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceIndexedCompositeStringUnique.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceLink.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, SearchResult.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, SearchInclude.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptParentChildLink.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMapGroupElementTarget.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMapGroupElement.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMapGroup.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMap.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptProperty.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptDesignation.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConcept.class)); - txTemplate.execute(t -> { + counter.addAndGet(expungeEverythingByType(SearchParamPresent.class)); + counter.addAndGet(expungeEverythingByType(ForcedId.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamDate.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamNumber.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamQuantity.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamString.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamToken.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamUri.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamCoords.class)); + counter.addAndGet(expungeEverythingByType(ResourceIndexedCompositeStringUnique.class)); + counter.addAndGet(expungeEverythingByType(ResourceLink.class)); + counter.addAndGet(expungeEverythingByType(SearchResult.class)); + counter.addAndGet(expungeEverythingByType(SearchInclude.class)); + counter.addAndGet(expungeEverythingByType(TermConceptParentChildLink.class)); + counter.addAndGet(expungeEverythingByType(TermConceptMapGroupElementTarget.class)); + counter.addAndGet(expungeEverythingByType(TermConceptMapGroupElement.class)); + counter.addAndGet(expungeEverythingByType(TermConceptMapGroup.class)); + counter.addAndGet(expungeEverythingByType(TermConceptMap.class)); + counter.addAndGet(expungeEverythingByType(TermConceptProperty.class)); + counter.addAndGet(expungeEverythingByType(TermConceptDesignation.class)); + counter.addAndGet(expungeEverythingByType(TermConcept.class)); + myTxTemplate.execute(t -> { for (TermCodeSystem next : myEntityManager.createQuery("SELECT c FROM " + TermCodeSystem.class.getName() + " c", TermCodeSystem.class).getResultList()) { next.setCurrentVersion(null); myEntityManager.merge(next); } return null; }); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermCodeSystemVersion.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermCodeSystem.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, SubscriptionTable.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceHistoryTag.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceTag.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, TagDefinition.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceHistoryTable.class)); - counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceTable.class)); - txTemplate.execute(t -> { + counter.addAndGet(expungeEverythingByType(TermCodeSystemVersion.class)); + counter.addAndGet(expungeEverythingByType(TermCodeSystem.class)); + counter.addAndGet(expungeEverythingByType(SubscriptionTable.class)); + counter.addAndGet(expungeEverythingByType(ResourceHistoryTag.class)); + counter.addAndGet(expungeEverythingByType(ResourceTag.class)); + counter.addAndGet(expungeEverythingByType(TagDefinition.class)); + counter.addAndGet(expungeEverythingByType(ResourceHistoryTable.class)); + counter.addAndGet(expungeEverythingByType(ResourceTable.class)); + myTxTemplate.execute(t -> { counter.addAndGet(doExpungeEverythingQuery("DELETE from " + org.hibernate.search.jpa.Search.class.getSimpleName() + " d")); return null; }); @@ -124,14 +127,14 @@ public class ExpungeEverythingService { ourLog.info("COMPLETED GLOBAL $expunge - Deleted {} rows", counter.get()); } - private int doExpungeEverythingQuery(TransactionTemplate txTemplate, Class theEntityType) { + public int expungeEverythingByType(Class theEntityType) { int outcome = 0; while (true) { StopWatch sw = new StopWatch(); @SuppressWarnings("ConstantConditions") - int count = txTemplate.execute(t -> { + int count = myTxTemplate.execute(t -> { CriteriaBuilder cb = myEntityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(theEntityType); cq.from(theEntityType); From 26ab115ff5ccabe29b195ddd3402ceb5cdb8121f Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Fri, 12 Jul 2019 13:34:32 -0400 Subject: [PATCH 3/5] changes.xml --- .../ca/uhn/fhir/interceptor/api/Pointcut.java | 28 +++++++++++++++++++ src/changes/changes.xml | 4 +++ 2 files changed, 32 insertions(+) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 9d64fe98466..bd248475101 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -1163,6 +1163,34 @@ public enum Pointcut { "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails" ), + /** + * Invoked before expungeEverything is called. + *

+ * Hooks will be passed a reference to a counter containing the current number of records that have been deleted. + * If the hook deletes any records, the hook is expected to increment this counter by the number of records deleted. + *

+ * Hooks may accept the following parameters: + *
    + *
  • java.util.concurrent.atomic.AtomicInteger - The counter holding the number of records deleted.
  • + *
  • + * ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that is about to be processed, including details such as the + * resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been + * pulled out of the servlet request. Note that the bean + * properties are not all guaranteed to be populated, depending on how early during processing the + * exception occurred. + *
  • + *
  • + * ca.uhn.fhir.rest.server.servlet.ServletRequestDetails - A bean containing details about the request that is about to be processed, including details such as the + * resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been + * pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will + * only be populated when operating in a RestfulServer implementation. It is provided as a convenience. + *
  • + *
+ *

+ * Hooks should return void. + *

+ */ + STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING( // Return type void.class, diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 58ab5ee9b26..b9f3f45c465 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -270,6 +270,10 @@ The _summary]]> element was not always respected when encoding JSON resources. + + Added a new Pointcut STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING that is called at the start of + the expungeEverything operation. + From 78aec06c4dc09a6eacbdb811b221ff0555bcbc6c Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Fri, 12 Jul 2019 13:38:45 -0400 Subject: [PATCH 4/5] changes.xml --- src/changes/changes.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index b9f3f45c465..70f83506b1f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -274,6 +274,10 @@ Added a new Pointcut STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING that is called at the start of the expungeEverything operation. + + Added RequestDetails to all Expunge operations. + + From accf57230b0b2b60ee782e65aa5ba18d7a5b7db4 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Fri, 12 Jul 2019 17:13:17 -0400 Subject: [PATCH 5/5] review feedback --- src/changes/changes.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 70f83506b1f..b9f3f45c465 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -274,10 +274,6 @@ Added a new Pointcut STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING that is called at the start of the expungeEverything operation. - - Added RequestDetails to all Expunge operations. - -