Work on multitenancy
This commit is contained in:
parent
ec6fe70acb
commit
9df4c58122
|
@ -25,8 +25,3 @@
|
|||
has been replaced with an equivalent `FhirContext.newFhirPath()`. The FhirPath expression language was initially
|
||||
called FluentPath before being renamed, so this change brings HAPI FHIR inline with the correct naming.
|
||||
"
|
||||
- item:
|
||||
type: change
|
||||
title: "The JPA server now shared a single set of tags for all versions of a resource, bringing it in line with the
|
||||
functional description in the FHIR specification. This means that it is no longer possible to modify the tags for
|
||||
a specific version of a resource, and also causes significant performance improvements in some cases."
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.junit.Test;
|
|||
import javax.servlet.ServletException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
@ -36,16 +37,19 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MultitenantR4Test.class);
|
||||
private MyInterceptor myTenantInterceptor;
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
myDaoConfig.setMultiTenancyEnabled(new DaoConfig().isMultiTenancyEnabled());
|
||||
|
||||
myInterceptorRegistry.unregisterInterceptorsIf(t -> t instanceof MyInterceptor);
|
||||
myInterceptor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,56 +78,84 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
|||
public void testCreateResourceWithTenant() {
|
||||
createUniqueCompositeSp();
|
||||
|
||||
int expectId = 3;
|
||||
LocalDate expectDate = LocalDate.of(2020, Month.JANUARY, 14);
|
||||
myInterceptorRegistry.registerInterceptor(new MyInterceptor(new TenantId(expectId, expectDate)));
|
||||
addTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
|
||||
addTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setName("org");
|
||||
IIdType orgId = myOrganizationDao.create(org).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.getMeta().addTag("http://system", "code", "diisplay");
|
||||
p.addName().setFamily("FAM");
|
||||
p.addIdentifier().setSystem("system").setValue("value");
|
||||
p.setBirthDate(new Date());
|
||||
p.getManagingOrganization().setReferenceElement(orgId);
|
||||
Long patientId = myPatientDao.create(p).getId().getIdPartAsLong();
|
||||
when(mySrd.getRequestId()).thenReturn("REQUEST_ID");
|
||||
Long patientId = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
runInTransaction(() -> {
|
||||
// HFJ_RESOURCE
|
||||
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
|
||||
assertEquals(expectId, resourceTable.getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, resourceTable.getTenantId().getTenantDate());
|
||||
assertEquals(3, resourceTable.getTenantId().getTenantId().intValue());
|
||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), resourceTable.getTenantId().getTenantDate());
|
||||
|
||||
resourceTable.getProfile()
|
||||
|
||||
// HFJ_RES_VER
|
||||
ResourceHistoryTable version = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, 1L);
|
||||
assertEquals(expectId, version.getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, version.getTenantId().getTenantDate());
|
||||
assertEquals(3, version.getTenantId().getTenantId().intValue());
|
||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), version.getTenantId().getTenantDate());
|
||||
|
||||
// HFJ_SPIDX_STRING
|
||||
List<ResourceIndexedSearchParamString> strings = myResourceIndexedSearchParamStringDao.findAllForResourceId(patientId);
|
||||
ourLog.info("\n * {}", strings.stream().map(ResourceIndexedSearchParamString::toString).collect(Collectors.joining("\n * ")));
|
||||
assertEquals(10, strings.size());
|
||||
assertEquals(expectId, strings.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, strings.get(0).getTenantId().getTenantDate());
|
||||
assertEquals(3, strings.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), strings.get(0).getTenantId().getTenantDate());
|
||||
|
||||
// HFJ_RES_LINK
|
||||
List<ResourceLink> resourceLinks = myResourceLinkDao.findAllForResourceId(patientId);
|
||||
assertEquals(1, resourceLinks.size());
|
||||
assertEquals(expectId, resourceLinks.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, resourceLinks.get(0).getTenantId().getTenantDate());
|
||||
assertEquals(3, resourceLinks.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), resourceLinks.get(0).getTenantId().getTenantDate());
|
||||
|
||||
// HFJ_RES_PARAM_PRESENT
|
||||
List<SearchParamPresent> presents = mySearchParamPresentDao.findAllForResource(resourceTable);
|
||||
assertEquals(3, presents.size());
|
||||
assertEquals(expectId, presents.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, presents.get(0).getTenantId().getTenantDate());
|
||||
assertEquals(3, presents.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), presents.get(0).getTenantId().getTenantDate());
|
||||
|
||||
// HFJ_IDX_CMP_STRING_UNIQ
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceId(patientId);
|
||||
assertEquals(3, uniques.size());
|
||||
assertEquals(expectId, uniques.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, uniques.get(0).getTenantId().getTenantDate());
|
||||
assertEquals(3, uniques.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), uniques.get(0).getTenantId().getTenantDate());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateResourceWithTenant() {
|
||||
createUniqueCompositeSp();
|
||||
|
||||
addTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
Long patientId = myPatientDao.create(p).getId().getIdPartAsLong();
|
||||
|
||||
p = new Patient();
|
||||
p.setId("Patient/" + patientId);
|
||||
p.setActive(false);
|
||||
myPatientDao.update(p);
|
||||
|
||||
runInTransaction(() -> {
|
||||
// HFJ_RES_VER
|
||||
ResourceHistoryTable resVer = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, 2);
|
||||
assertEquals(tenantId, resVer.getTenantId().getTenantId().intValue());
|
||||
assertEquals(tenantDate, resVer.getTenantId().getTenantDate());
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -154,19 +186,27 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
|||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
||||
public void addTenant(int theTenantId, LocalDate theTenantDate) {
|
||||
if (myTenantInterceptor == null) {
|
||||
myTenantInterceptor = new MyInterceptor();
|
||||
myInterceptorRegistry.registerInterceptor(myInterceptor);
|
||||
}
|
||||
myTenantInterceptor.addTenant(new TenantId(theTenantId, theTenantDate));
|
||||
}
|
||||
|
||||
@Interceptor
|
||||
public static class MyInterceptor {
|
||||
|
||||
private final List<TenantId> myTenantIds;
|
||||
private final List<TenantId> myTenantIds = new ArrayList<>();
|
||||
|
||||
public MyInterceptor(TenantId theTenantId) {
|
||||
public void addTenant(TenantId theTenantId) {
|
||||
Validate.notNull(theTenantId);
|
||||
myTenantIds = Collections.singletonList(theTenantId);
|
||||
myTenantIds.add(theTenantId);
|
||||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_TENANT_IDENTIFY_CREATE)
|
||||
public TenantId tenantIdentifyCreate() {
|
||||
TenantId retVal = myTenantIds.get(0);
|
||||
TenantId retVal = myTenantIds.remove(0);
|
||||
ourLog.info("Returning tenant ID: {}", retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -57,10 +57,10 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
init400(); // 20190401 - 20190814
|
||||
init410(); // 20190815 - 20191014
|
||||
init420(); // 20191015 - 20200217
|
||||
init430(); // 20200218 - present
|
||||
init500(); // 20200218 - present
|
||||
}
|
||||
|
||||
protected void init430() { // 20200218 - present
|
||||
protected void init500() { // 20200218 - present
|
||||
Builder version = forVersion(VersionEnum.V4_3_0);
|
||||
|
||||
// Eliminate circular dependency.
|
||||
|
@ -68,6 +68,9 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_RES_VER").dropColumn("20200218.2", "FORCED_ID_PID");
|
||||
version.onTable("HFJ_RES_VER").addForeignKey("20200218.3", "FK_RESOURCE_HISTORY_RESOURCE").toColumn("RES_ID").references("HFJ_RESOURCE", "RES_ID");
|
||||
version.onTable("HFJ_RES_VER").modifyColumn("20200220.1", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||
|
||||
// Add mlutiitenancy
|
||||
version.onTable("HFJ_RESOURCE").dropColumn("20200327.1", "RES_PROFILE");
|
||||
}
|
||||
|
||||
protected void init420() { // 20191015 - 20200217
|
||||
|
|
|
@ -60,7 +60,6 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
|
|||
public class ResourceTable extends BaseHasResource implements Serializable, IBasePersistedResource, IResourceLookup {
|
||||
public static final int RESTYPE_LEN = 40;
|
||||
private static final int MAX_LANGUAGE_LENGTH = 20;
|
||||
private static final int MAX_PROFILE_LENGTH = 200;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
@ -167,10 +166,6 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsUriPopulated;
|
||||
|
||||
@Column(name = "RES_PROFILE", length = MAX_PROFILE_LENGTH, nullable = true)
|
||||
@OptimisticLock(excluded = true)
|
||||
private String myProfile;
|
||||
|
||||
// Added in 3.0.0 - Should make this a primitive Boolean at some point
|
||||
@OptimisticLock(excluded = true)
|
||||
@Column(name = "SP_CMPSTR_UNIQ_PRESENT")
|
||||
|
@ -402,17 +397,6 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
getParamsUri().addAll(theParamsUri);
|
||||
}
|
||||
|
||||
public String getProfile() {
|
||||
return myProfile;
|
||||
}
|
||||
|
||||
public void setProfile(String theProfile) {
|
||||
if (defaultString(theProfile).length() > MAX_PROFILE_LENGTH) {
|
||||
throw new UnprocessableEntityException("Profile name exceeds maximum length of " + MAX_PROFILE_LENGTH + " chars: " + theProfile);
|
||||
}
|
||||
myProfile = theProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getResourceId() {
|
||||
return getId();
|
||||
|
|
|
@ -50,6 +50,7 @@ public class ResourceTag extends BaseTag {
|
|||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourceId;
|
||||
|
||||
@Embedded
|
||||
private TenantId myTenantId;
|
||||
|
||||
|
|
Loading…
Reference in New Issue