Improve logging for expunge operation

This commit is contained in:
James Agnew 2018-09-29 18:38:27 -04:00
parent 3e445faf47
commit 9f7e21fec6
5 changed files with 53 additions and 16 deletions

View File

@ -228,6 +228,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
protected ExpungeOutcome doExpunge(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions) { protected ExpungeOutcome doExpunge(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions) {
TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager); TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager);
ourLog.info("Expunge: ResourceName[{}] Id[{}] Version[{}] Options[{}]", theResourceName, theResourceId, theVersion, theExpungeOptions);
if (!getConfig().isExpungeEnabled()) { if (!getConfig().isExpungeEnabled()) {
throw new MethodNotAllowedException("$expunge is not enabled on this server"); throw new MethodNotAllowedException("$expunge is not enabled on this server");
@ -249,19 +250,30 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
Pageable page = PageRequest.of(0, remainingCount.get()); Pageable page = PageRequest.of(0, remainingCount.get());
Slice<Long> resourceIds = txTemplate.execute(t -> { Slice<Long> resourceIds = txTemplate.execute(t -> {
if (theResourceId != null) { if (theResourceId != null) {
return myResourceTableDao.findIdsOfDeletedResourcesOfType(page, theResourceId, theResourceName); Slice<Long> ids = myResourceTableDao.findIdsOfDeletedResourcesOfType(page, theResourceId, theResourceName);
ourLog.info("Expunging {} deleted resources of type[{}] and ID[{}]", ids.getNumberOfElements(), theResourceName, theResourceId);
return ids;
} else { } else {
if (theResourceName != null) { if (theResourceName != null) {
return myResourceTableDao.findIdsOfDeletedResourcesOfType(page, theResourceName); Slice<Long> ids = myResourceTableDao.findIdsOfDeletedResourcesOfType(page, theResourceName);
ourLog.info("Expunging {} deleted resources of type[{}]", ids.getNumberOfElements(), theResourceName);
return ids;
} else { } else {
return myResourceTableDao.findIdsOfDeletedResources(page); Slice<Long> ids = myResourceTableDao.findIdsOfDeletedResources(page);
ourLog.info("Expunging {} deleted resources (all types)", ids.getNumberOfElements(), theResourceName);
return ids;
} }
} }
}); });
/*
* Delete historical versions
*/
for (Long next : resourceIds) { for (Long next : resourceIds) {
txTemplate.execute(t -> { txTemplate.execute(t -> {
expungeHistoricalVersionsOfId(next, remainingCount); expungeHistoricalVersionsOfId(next, remainingCount);
if (remainingCount.get() <= 0) { if (remainingCount.get() <= 0) {
ourLog.info("Expunge limit has been hit - Stopping operation");
return toExpungeOutcome(theExpungeOptions, remainingCount); return toExpungeOutcome(theExpungeOptions, remainingCount);
} }
return null; return null;
@ -273,8 +285,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
*/ */
for (Long next : resourceIds) { for (Long next : resourceIds) {
txTemplate.execute(t -> { txTemplate.execute(t -> {
expungeCurrentVersionOfResource(next); expungeCurrentVersionOfResource(next, remainingCount);
if (remainingCount.get() <= 0) { if (remainingCount.get() <= 0) {
ourLog.info("Expunge limit has been hit - Stopping operation");
return toExpungeOutcome(theExpungeOptions, remainingCount); return toExpungeOutcome(theExpungeOptions, remainingCount);
} }
return null; return null;
@ -384,7 +397,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
ourLog.info("Query affected {} rows in {}: {}", outcome, sw.toString(), theQuery); ourLog.info("Query affected {} rows in {}: {}", outcome, sw.toString(), theQuery);
} }
private void expungeCurrentVersionOfResource(Long theResourceId) { private void expungeCurrentVersionOfResource(Long theResourceId, AtomicInteger theRemainingCount) {
ResourceTable resource = myResourceTableDao.findById(theResourceId).orElseThrow(IllegalStateException::new); ResourceTable resource = myResourceTableDao.findById(theResourceId).orElseThrow(IllegalStateException::new);
ResourceHistoryTable currentVersion = myResourceHistoryTableDao.findForIdAndVersion(resource.getId(), resource.getVersion()); ResourceHistoryTable currentVersion = myResourceHistoryTableDao.findForIdAndVersion(resource.getId(), resource.getVersion());
@ -392,7 +405,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
expungeHistoricalVersion(currentVersion.getId()); expungeHistoricalVersion(currentVersion.getId());
} }
ourLog.info("Deleting current version of resource {}", resource.getIdDt().getValue()); ourLog.info("Expunging current version of resource {}", resource.getIdDt().getValue());
myResourceIndexedSearchParamUriDao.deleteAll(resource.getParamsUri()); myResourceIndexedSearchParamUriDao.deleteAll(resource.getParamsUri());
myResourceIndexedSearchParamCoordsDao.deleteAll(resource.getParamsCoords()); myResourceIndexedSearchParamCoordsDao.deleteAll(resource.getParamsCoords());
@ -414,6 +427,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
myResourceTableDao.delete(resource); myResourceTableDao.delete(resource);
theRemainingCount.decrementAndGet();
} }
protected void expungeHistoricalVersion(Long theNextVersionId) { protected void expungeHistoricalVersion(Long theNextVersionId) {
@ -427,9 +441,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
protected void expungeHistoricalVersionsOfId(Long theResourceId, AtomicInteger theRemainingCount) { protected void expungeHistoricalVersionsOfId(Long theResourceId, AtomicInteger theRemainingCount) {
ResourceTable resource = myResourceTableDao.findById(theResourceId).orElseThrow(IllegalArgumentException::new); ResourceTable resource = myResourceTableDao.findById(theResourceId).orElseThrow(IllegalArgumentException::new);
Pageable page = new PageRequest(0, theRemainingCount.get()); Pageable page = PageRequest.of(0, theRemainingCount.get());
Slice<Long> versionIds = myResourceHistoryTableDao.findForResourceId(page, resource.getId(), resource.getVersion()); Slice<Long> versionIds = myResourceHistoryTableDao.findForResourceId(page, resource.getId(), resource.getVersion());
ourLog.info("Found {} versions of resource {} to expunge", versionIds.getNumberOfElements(), resource.getIdDt().getValue());
for (Long nextVersionId : versionIds) { for (Long nextVersionId : versionIds) {
expungeHistoricalVersion(nextVersionId); expungeHistoricalVersion(nextVersionId);
if (theRemainingCount.decrementAndGet() <= 0) { if (theRemainingCount.decrementAndGet() <= 0) {

View File

@ -1867,6 +1867,9 @@ public class SearchBuilder implements ISearchBuilder {
private void searchForIdsWithAndOr(String theResourceName, String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams) { private void searchForIdsWithAndOr(String theResourceName, String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams) {
/*
* Filter out
*/
for (int andListIdx = 0; andListIdx < theAndOrParams.size(); andListIdx++) { for (int andListIdx = 0; andListIdx < theAndOrParams.size(); andListIdx++) {
List<? extends IQueryParameterType> nextOrList = theAndOrParams.get(andListIdx); List<? extends IQueryParameterType> nextOrList = theAndOrParams.get(andListIdx);

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.util;
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -20,12 +20,25 @@ package ca.uhn.fhir.jpa.util;
* #L% * #L%
*/ */
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class ExpungeOptions { public class ExpungeOptions {
private int myLimit = 1000; private int myLimit = 1000;
private boolean myExpungeOldVersions; private boolean myExpungeOldVersions;
private boolean myExpungeDeletedResources; private boolean myExpungeDeletedResources;
private boolean myExpungeEverything; private boolean myExpungeEverything;
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("myLimit", myLimit)
.append("myExpungeOldVersions", myExpungeOldVersions)
.append("myExpungeDeletedResources", myExpungeDeletedResources)
.append("myExpungeEverything", myExpungeEverything)
.toString();
}
/** /**
* The maximum number of resources versions to expunge * The maximum number of resources versions to expunge
*/ */
@ -33,6 +46,13 @@ public class ExpungeOptions {
return myLimit; return myLimit;
} }
/**
* The maximum number of resource versions to expunge
*/
public void setLimit(int theLimit) {
myLimit = theLimit;
}
public boolean isExpungeEverything() { public boolean isExpungeEverything() {
return myExpungeEverything; return myExpungeEverything;
} }
@ -42,13 +62,6 @@ public class ExpungeOptions {
return this; return this;
} }
/**
* The maximum number of resource versions to expunge
*/
public void setLimit(int theLimit) {
myLimit = theLimit;
}
public boolean isExpungeDeletedResources() { public boolean isExpungeDeletedResources() {
return myExpungeDeletedResources; return myExpungeDeletedResources;
} }

View File

@ -416,6 +416,7 @@ public abstract class BaseJpaTest {
if (sw.getMillis() >= theTimeout) { if (sw.getMillis() >= theTimeout) {
fail("Size " + theCallable.call() + " is != target " + theTarget); fail("Size " + theCallable.call() + " is != target " + theTarget);
} }
Thread.sleep(500);
} }
} }

View File

@ -376,6 +376,11 @@
not try to read request parameters from the content stream. This avoids an incompatibility with not try to read request parameters from the content stream. This avoids an incompatibility with
new versions of Jetty. new versions of Jetty.
</action> </action>
<action type="fix" issue="1050">
Custom profile names when not matching standard FHIR profile names, are now
handled properly by the validator. Thanks to Anthony Sute
for the Pull Request!
</action>
</release> </release>
<release version="3.4.0" date="2018-05-28"> <release version="3.4.0" date="2018-05-28">
<action type="add"> <action type="add">