This commit is contained in:
Ken Stevens 2021-09-09 01:00:12 -04:00
parent 67c8216d73
commit 5bc571d97d
13 changed files with 75 additions and 48 deletions

View File

@ -80,11 +80,11 @@ public class ResourceVersionSvcDaoImpl implements IResourceVersionSvc {
} }
@Override @Override
public ResourceVersionMap getLatestVersionIdsForResourceIds(RequestPartitionId thePartitionId, List<IIdType> theIds) { public ResourcePersistentIdMap getLatestVersionIdsForResourceIds(RequestPartitionId thePartitionId, List<IIdType> theIds) {
List<ResourcePersistentId> resourcePersistentIds = myIdHelperService.resolveResourcePersistentIdsWithCache(thePartitionId, List<ResourcePersistentId> resourcePersistentIds = myIdHelperService.resolveResourcePersistentIdsWithCache(thePartitionId,
new ArrayList<>(theIds)); new ArrayList<>(theIds));
return ResourceVersionMap.fromResourcePersistentIds(resourcePersistentIds); return ResourcePersistentIdMap.fromResourcePersistentIds(resourcePersistentIds);
} }
} }

View File

@ -31,7 +31,7 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome; import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.api.model.LazyDaoMethodOutcome; import ca.uhn.fhir.jpa.api.model.LazyDaoMethodOutcome;
import ca.uhn.fhir.jpa.cache.IResourceVersionSvc; import ca.uhn.fhir.jpa.cache.IResourceVersionSvc;
import ca.uhn.fhir.jpa.cache.ResourceVersionMap; import ca.uhn.fhir.jpa.cache.ResourcePersistentIdMap;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -212,7 +212,7 @@ public abstract class BaseStorageDao {
IIdType referenceElement = nextReference.getReferenceElement(); IIdType referenceElement = nextReference.getReferenceElement();
if (!referenceElement.hasBaseUrl()) { if (!referenceElement.hasBaseUrl()) {
ResourceVersionMap resourceVersionMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(), ResourcePersistentIdMap resourceVersionMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(),
Collections.singletonList(referenceElement) Collections.singletonList(referenceElement)
); );
@ -224,7 +224,7 @@ public abstract class BaseStorageDao {
if (resourceVersionMap.containsKey(referenceElement)) { if (resourceVersionMap.containsKey(referenceElement)) {
// the resource exists... latest id // the resource exists... latest id
// will be the value in the ResourcePersistentId // will be the value in the ResourcePersistentId
version = resourceVersionMap.getVersionAsLong(referenceElement); version = resourceVersionMap.getResourcePersistentId(referenceElement).getVersion();
} else if (myDaoConfig.isAutoCreatePlaceholderReferenceTargets()) { } else if (myDaoConfig.isAutoCreatePlaceholderReferenceTargets()) {
// if idToPID doesn't contain object // if idToPID doesn't contain object
// but autcreateplaceholders is on // but autcreateplaceholders is on

View File

@ -36,7 +36,7 @@ import ca.uhn.fhir.jpa.api.model.DeleteConflict;
import ca.uhn.fhir.jpa.api.model.DeleteConflictList; import ca.uhn.fhir.jpa.api.model.DeleteConflictList;
import ca.uhn.fhir.jpa.api.model.DeleteMethodOutcome; import ca.uhn.fhir.jpa.api.model.DeleteMethodOutcome;
import ca.uhn.fhir.jpa.cache.IResourceVersionSvc; import ca.uhn.fhir.jpa.cache.IResourceVersionSvc;
import ca.uhn.fhir.jpa.cache.ResourceVersionMap; import ca.uhn.fhir.jpa.cache.ResourcePersistentIdMap;
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService; import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
import ca.uhn.fhir.jpa.delete.DeleteConflictService; import ca.uhn.fhir.jpa.delete.DeleteConflictService;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
@ -1271,7 +1271,7 @@ public abstract class BaseTransactionProcessor {
// get a map of // get a map of
// existing ids -> PID (for resources that exist in the DB) // existing ids -> PID (for resources that exist in the DB)
// should this be allPartitions? // should this be allPartitions?
ResourceVersionMap resourceVersionMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(), ResourcePersistentIdMap resourceVersionMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(),
theReferencesToAutoVersion.stream() theReferencesToAutoVersion.stream()
.map(IBaseReference::getReferenceElement).collect(Collectors.toList())); .map(IBaseReference::getReferenceElement).collect(Collectors.toList()));

View File

@ -21,12 +21,12 @@ public class ResourceVersionCacheSvcTest extends BaseJpaR4Test {
IIdType patientId = myPatientDao.create(patient).getId(); IIdType patientId = myPatientDao.create(patient).getId();
ResourceVersionMap versionMap = myResourceVersionCacheSvc.getVersionMap("Patient", SearchParameterMap.newSynchronous()); ResourceVersionMap versionMap = myResourceVersionCacheSvc.getVersionMap("Patient", SearchParameterMap.newSynchronous());
assertEquals(1, versionMap.size()); assertEquals(1, versionMap.size());
assertEquals("1", versionMap.getVersion(patientId)); assertEquals(1L, versionMap.getVersion(patientId));
patient.setGender(Enumerations.AdministrativeGender.MALE); patient.setGender(Enumerations.AdministrativeGender.MALE);
myPatientDao.update(patient); myPatientDao.update(patient);
versionMap = myResourceVersionCacheSvc.getVersionMap("Patient", SearchParameterMap.newSynchronous()); versionMap = myResourceVersionCacheSvc.getVersionMap("Patient", SearchParameterMap.newSynchronous());
assertEquals(1, versionMap.size()); assertEquals(1, versionMap.size());
assertEquals("2", versionMap.getVersion(patientId)); assertEquals(2L, versionMap.getVersion(patientId));
} }
} }

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.interceptor.executor.InterceptorService; import ca.uhn.fhir.interceptor.executor.InterceptorService;
import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.cache.IResourceVersionSvc;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.dao.r4.TransactionProcessorVersionAdapterR4; import ca.uhn.fhir.jpa.dao.r4.TransactionProcessorVersionAdapterR4;
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService; import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
@ -70,6 +71,8 @@ public class TransactionProcessorTest {
private MatchUrlService myMatchUrlService; private MatchUrlService myMatchUrlService;
@MockBean @MockBean
private IRequestPartitionHelperSvc myRequestPartitionHelperSvc; private IRequestPartitionHelperSvc myRequestPartitionHelperSvc;
@MockBean
private IResourceVersionSvc myResourceVersionSvc;
@MockBean(answer = Answers.RETURNS_DEEP_STUBS) @MockBean(answer = Answers.RETURNS_DEEP_STUBS)
private SessionImpl mySession; private SessionImpl mySession;

View File

@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.dao.index;
import ca.uhn.fhir.interceptor.model.RequestPartitionId; import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.cache.ResourceVersionMap; import ca.uhn.fhir.jpa.cache.ResourcePersistentIdMap;
import ca.uhn.fhir.jpa.cache.ResourceVersionSvcDaoImpl; import ca.uhn.fhir.jpa.cache.ResourceVersionSvcDaoImpl;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
@ -134,7 +134,7 @@ public class ResourceVersionSvcTest {
mockReturnsFor_getIdsOfExistingResources(pack); mockReturnsFor_getIdsOfExistingResources(pack);
// test // test
ResourceVersionMap retMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(), ResourcePersistentIdMap retMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(),
Collections.singletonList(type)); Collections.singletonList(type));
Assertions.assertTrue(retMap.containsKey(type)); Assertions.assertTrue(retMap.containsKey(type));
@ -149,7 +149,7 @@ public class ResourceVersionSvcTest {
mock_resolveResourcePersistentIdsWithCache_toReturnNothing(); mock_resolveResourcePersistentIdsWithCache_toReturnNothing();
// test // test
ResourceVersionMap retMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(), ResourcePersistentIdMap retMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(RequestPartitionId.allPartitions(),
Collections.singletonList(type)); Collections.singletonList(type));
Assertions.assertTrue(retMap.isEmpty()); Assertions.assertTrue(retMap.isEmpty());
@ -171,7 +171,7 @@ public class ResourceVersionSvcTest {
mockReturnsFor_getIdsOfExistingResources(pack); mockReturnsFor_getIdsOfExistingResources(pack);
// test // test
ResourceVersionMap retMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds( ResourcePersistentIdMap retMap = myResourceVersionSvc.getLatestVersionIdsForResourceIds(
RequestPartitionId.allPartitions(), RequestPartitionId.allPartitions(),
Arrays.asList(type, type2) Arrays.asList(type, type2)
); );

View File

@ -14,6 +14,7 @@ import ca.uhn.fhir.jpa.cache.ResourceChangeListenerCache;
import ca.uhn.fhir.jpa.cache.ResourceChangeListenerCacheFactory; import ca.uhn.fhir.jpa.cache.ResourceChangeListenerCacheFactory;
import ca.uhn.fhir.jpa.cache.ResourceChangeListenerCacheRefresherImpl; import ca.uhn.fhir.jpa.cache.ResourceChangeListenerCacheRefresherImpl;
import ca.uhn.fhir.jpa.cache.ResourceChangeListenerRegistryImpl; import ca.uhn.fhir.jpa.cache.ResourceChangeListenerRegistryImpl;
import ca.uhn.fhir.jpa.cache.ResourcePersistentIdMap;
import ca.uhn.fhir.jpa.cache.ResourceVersionMap; import ca.uhn.fhir.jpa.cache.ResourceVersionMap;
import ca.uhn.fhir.jpa.dao.JpaResourceDao; import ca.uhn.fhir.jpa.dao.JpaResourceDao;
import ca.uhn.fhir.jpa.dao.TransactionProcessor; import ca.uhn.fhir.jpa.dao.TransactionProcessor;
@ -330,7 +331,7 @@ public class GiantTransactionPerfTest {
} }
@Override @Override
public ResourceVersionMap getLatestVersionIdsForResourceIds(RequestPartitionId thePartition, List<IIdType> theIds) { public ResourcePersistentIdMap getLatestVersionIdsForResourceIds(RequestPartitionId thePartition, List<IIdType> theIds) {
return null; return null;
} }
} }

View File

@ -40,5 +40,5 @@ public interface IResourceVersionSvc {
return getVersionMap(RequestPartitionId.allPartitions(), theResourceName, theSearchParamMap); return getVersionMap(RequestPartitionId.allPartitions(), theResourceName, theSearchParamMap);
} }
ResourceVersionMap getLatestVersionIdsForResourceIds(RequestPartitionId thePartition, List<IIdType> theIds); ResourcePersistentIdMap getLatestVersionIdsForResourceIds(RequestPartitionId thePartition, List<IIdType> theIds);
} }

View File

@ -173,8 +173,8 @@ public class ResourceChangeListenerCacheRefresherImpl implements IResourceChange
List<IIdType> updatedIds = new ArrayList<>(); List<IIdType> updatedIds = new ArrayList<>();
for (IIdType id : theNewResourceVersionMap.keySet()) { for (IIdType id : theNewResourceVersionMap.keySet()) {
String previousValue = theOldResourceVersionCache.put(id, theNewResourceVersionMap.get(id)); Long previousValue = theOldResourceVersionCache.put(id, theNewResourceVersionMap.get(id));
IIdType newId = id.withVersion(theNewResourceVersionMap.get(id)); IIdType newId = id.withVersion(theNewResourceVersionMap.get(id).toString());
if (previousValue == null) { if (previousValue == null) {
createdIds.add(newId); createdIds.add(newId);
} else if (!theNewResourceVersionMap.get(id).equals(previousValue)) { } else if (!theNewResourceVersionMap.get(id).equals(previousValue)) {

View File

@ -0,0 +1,39 @@
package ca.uhn.fhir.jpa.cache;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import org.hl7.fhir.instance.model.api.IIdType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ResourcePersistentIdMap {
private final Map<IIdType, ResourcePersistentId> myMap = new HashMap<>();
public static ResourcePersistentIdMap fromResourcePersistentIds(List<ResourcePersistentId> theResourcePersistentIds) {
ResourcePersistentIdMap retval = new ResourcePersistentIdMap();
theResourcePersistentIds.forEach(retval::add);
return retval;
}
private void add(ResourcePersistentId theResourcePersistentId) {
IIdType id = theResourcePersistentId.getAssociatedResourceId();
myMap.put(id.toUnqualifiedVersionless(), theResourcePersistentId);
}
public boolean containsKey(IIdType theId) {
return myMap.containsKey(theId.toUnqualifiedVersionless());
}
public ResourcePersistentId getResourcePersistentId(IIdType theId) {
return myMap.get(theId.toUnqualifiedVersionless());
}
public boolean isEmpty() {
return myMap.isEmpty();
}
public int size() {
return myMap.size();
}
}

View File

@ -32,7 +32,7 @@ import java.util.Set;
* detect resources that were modified on remote servers in our cluster. * detect resources that were modified on remote servers in our cluster.
*/ */
public class ResourceVersionCache { public class ResourceVersionCache {
private final Map<IIdType, String> myVersionMap = new HashMap<>(); private final Map<IIdType, Long> myVersionMap = new HashMap<>();
public void clear() { public void clear() {
myVersionMap.clear(); myVersionMap.clear();
@ -43,15 +43,15 @@ public class ResourceVersionCache {
* @param theVersion * @param theVersion
* @return previous value * @return previous value
*/ */
public String put(IIdType theResourceId, String theVersion) { public Long put(IIdType theResourceId, Long theVersion) {
return myVersionMap.put(new IdDt(theResourceId).toVersionless(), theVersion); return myVersionMap.put(new IdDt(theResourceId).toVersionless(), theVersion);
} }
public String getVersionForResourceId(IIdType theResourceId) { public Long getVersionForResourceId(IIdType theResourceId) {
return myVersionMap.get(new IdDt(theResourceId)); return myVersionMap.get(new IdDt(theResourceId));
} }
public String removeResourceId(IIdType theResourceId) { public Long removeResourceId(IIdType theResourceId) {
return myVersionMap.remove(new IdDt(theResourceId)); return myVersionMap.remove(new IdDt(theResourceId));
} }

View File

@ -22,9 +22,10 @@ package ca.uhn.fhir.jpa.cache;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -37,9 +38,10 @@ import java.util.Set;
* This immutable map holds a copy of current resource versions read from the repository. * This immutable map holds a copy of current resource versions read from the repository.
*/ */
public class ResourceVersionMap { public class ResourceVersionMap {
private static final Logger ourLog = LoggerFactory.getLogger(ResourceVersionMap.class);
private final Set<IIdType> mySourceIds = new HashSet<>(); private final Set<IIdType> mySourceIds = new HashSet<>();
// Key versionless id, value version // Key versionless id, value version
private final Map<IIdType, String> myMap = new HashMap<>(); private final Map<IIdType, Long> myMap = new HashMap<>();
private ResourceVersionMap() {} private ResourceVersionMap() {}
public static ResourceVersionMap fromResourceTableEntities(List<ResourceTable> theEntities) { public static ResourceVersionMap fromResourceTableEntities(List<ResourceTable> theEntities) {
@ -58,19 +60,17 @@ public class ResourceVersionMap {
return new ResourceVersionMap(); return new ResourceVersionMap();
} }
public static ResourceVersionMap fromResourcePersistentIds(List<ResourcePersistentId> theResourcePersistentIds) {
ResourceVersionMap retval = new ResourceVersionMap();
theResourcePersistentIds.forEach(resourcePersistentId -> retval.add(resourcePersistentId.getAssociatedResourceId()));
return retval;
}
private void add(IIdType theId) { private void add(IIdType theId) {
if (theId.getVersionIdPart() == null) {
ourLog.warn("Not storing {} in ResourceVersionMap because it does not have a version.", theId);
return;
}
IdDt id = new IdDt(theId); IdDt id = new IdDt(theId);
mySourceIds.add(id); mySourceIds.add(id);
myMap.put(id.toUnqualifiedVersionless(), id.getVersionIdPart()); myMap.put(id.toUnqualifiedVersionless(), id.getVersionIdPartAsLong());
} }
public String getVersion(IIdType theResourceId) { public Long getVersion(IIdType theResourceId) {
return get(theResourceId); return get(theResourceId);
} }
@ -86,7 +86,7 @@ public class ResourceVersionMap {
return Collections.unmodifiableSet(mySourceIds); return Collections.unmodifiableSet(mySourceIds);
} }
public String get(IIdType theId) { public Long get(IIdType theId) {
return myMap.get(new IdDt(theId.toUnqualifiedVersionless())); return myMap.get(new IdDt(theId.toUnqualifiedVersionless()));
} }
@ -94,16 +94,6 @@ public class ResourceVersionMap {
return myMap.containsKey(new IdDt(theId.toUnqualifiedVersionless())); return myMap.containsKey(new IdDt(theId.toUnqualifiedVersionless()));
} }
public ResourcePersistentId getResourcePersistentId(IIdType theId) {
ResourcePersistentId retval = ResourcePersistentId.fromIIdType(theId);
retval.setVersion(getVersionAsLong(theId));
return retval;
}
public Long getVersionAsLong(IIdType theId) {
return Long.valueOf(getVersion(theId));
}
public boolean isEmpty() { public boolean isEmpty() {
return myMap.isEmpty(); return myMap.isEmpty();
} }

View File

@ -125,10 +125,4 @@ public class ResourcePersistentId {
} }
return retVal; return retVal;
} }
public static ResourcePersistentId fromIIdType(IIdType theId) {
ResourcePersistentId retval = new ResourcePersistentId(theId);
retval.setAssociatedResourceId(theId);
return retval;
}
} }