Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/main/java/io/weaviate/client/v1/schema/Schema.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.weaviate.client.v1.schema.api.TenantsCreator;
import io.weaviate.client.v1.schema.api.TenantsDeleter;
import io.weaviate.client.v1.schema.api.TenantsGetter;
import io.weaviate.client.v1.schema.api.TenantsUpdater;

public class Schema {
private final Config config;
Expand Down Expand Up @@ -69,6 +70,10 @@ public TenantsCreator tenantsCreator() {
return new TenantsCreator(httpClient, config);
}

public TenantsUpdater tenantsUpdater() {
return new TenantsUpdater(httpClient, config);
}

public TenantsDeleter tenantsDeleter() {
return new TenantsDeleter(httpClient, config);
}
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/io/weaviate/client/v1/schema/api/TenantsUpdater.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.weaviate.client.v1.schema.api;

import io.weaviate.client.Config;
import io.weaviate.client.base.BaseClient;
import io.weaviate.client.base.ClientResult;
import io.weaviate.client.base.Response;
import io.weaviate.client.base.Result;
import io.weaviate.client.base.http.HttpClient;
import io.weaviate.client.base.util.UrlEncoder;
import io.weaviate.client.v1.schema.model.Tenant;
import org.apache.http.HttpStatus;

public class TenantsUpdater extends BaseClient<Tenant[]> implements ClientResult<Boolean> {

private String className;
private Tenant[] tenants;

public TenantsUpdater(HttpClient httpClient, Config config) {
super(httpClient, config);
}

public TenantsUpdater withClassName(String className) {
this.className = className;
return this;
}

public TenantsUpdater withTenants(Tenant... tenants) {
this.tenants = tenants;
return this;
}

@Override
public Result<Boolean> run() {
String path = String.format("/schema/%s/tenants", UrlEncoder.encodePathParam(className));
Response<Tenant[]> resp = sendPutRequest(path, tenants, Tenant[].class);
return new Result<>(resp.getStatusCode(), resp.getStatusCode() == HttpStatus.SC_OK, resp.getErrors());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.weaviate.client.v1.schema.model;

public interface ActivityStatus {
String HOT = "HOT";
String WARM = "WARM";
String COLD = "COLD";
String FROZEN = "FROZEN";
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class Tenant {
String name;
String activityStatus;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
import io.weaviate.client.base.WeaviateError;
import io.weaviate.client.base.WeaviateErrorMessage;
import io.weaviate.client.v1.data.model.WeaviateObject;
import io.weaviate.client.v1.schema.model.ActivityStatus;
import io.weaviate.client.v1.schema.model.Tenant;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.STRING;
Expand Down Expand Up @@ -70,4 +74,51 @@ public <T> void error(Result<T> result, T expectedValue, int expectedStatusCode,
.extracting(m -> ((WeaviateErrorMessage) m).getMessage()).asInstanceOf(STRING)
.contains(expectedContains);
}

public void tenantActive(String className, String tenantName) {
tenantStatus(className, tenantName, ActivityStatus.HOT);
}

public void tenantInactive(String className, String tenantName) {
tenantStatus(className, tenantName, ActivityStatus.COLD);
}

private void tenantStatus(String className, String tenantName, String activityStatus) {
Result<List<Tenant>> result = client.schema().tenantsGetter()
.withClassName(className)
.run();

assertThat(result).isNotNull()
.returns(false, Result::hasErrors)
.extracting(Result::getResult).isNotNull();

Optional<Tenant> maybeTenant = result.getResult().stream()
.filter(Objects::nonNull)
.filter(tenant -> tenantName.equals(tenant.getName()))
.filter(tenant -> activityStatus.equals(tenant.getActivityStatus()))
.findFirst();

assertThat(maybeTenant).isNotEmpty();
}

public void tenantActiveGetsObjects(String className, String tenantName, int objectsCount) {
Result<List<WeaviateObject>> result = client.data().objectsGetter()
.withClassName(className)
.withTenant(tenantName)
.run();

assertThat(result).isNotNull()
.returns(false, Result::hasErrors)
.extracting(Result::getResult).asList()
.hasSize(objectsCount);
}

public void tenantInactiveGetsNoObjects(String className, String tenantName) {
Result<List<WeaviateObject>> result = client.data().objectsGetter()
.withClassName(className)
.withTenant(tenantName)
.run();

error(result, null, 422, "tenant not active");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public class WeaviateTestGenerics {
));
}

public static final Tenant TENANT_1 = Tenant.builder()
.name("TenantNo1")
.build();
public static final Tenant TENANT_2 = Tenant.builder()
.name("TenantNo2")
.build();


public void createWeaviateTestSchemaFood(WeaviateClient client) {
createWeaviateTestSchemaFood(client, false);
Expand Down Expand Up @@ -368,27 +375,23 @@ private void createSchema(WeaviateClient client, WeaviateClass cl) {
}


public void createTenantsPizza(WeaviateClient client, String... tenants) {
public void createTenantsPizza(WeaviateClient client, Tenant... tenants) {
createTenants(client, "Pizza", tenants);
}

public void createTenantsSoup(WeaviateClient client, String... tenants) {
public void createTenantsSoup(WeaviateClient client, Tenant... tenants) {
createTenants(client, "Soup", tenants);
}

public void createTenantsFood(WeaviateClient client, String... tenants) {
public void createTenantsFood(WeaviateClient client, Tenant... tenants) {
createTenantsPizza(client, tenants);
createTenantsSoup(client, tenants);
}

private void createTenants(WeaviateClient client, String className, String[] tenants) {
Tenant[] t = Arrays.stream(tenants)
.map(tenant -> Tenant.builder().name(tenant).build())
.toArray(Tenant[]::new);

private void createTenants(WeaviateClient client, String className, Tenant[] tenants) {
Result<Boolean> createStatus = client.schema().tenantsCreator()
.withClassName(className)
.withTenants(t)
.withTenants(tenants)
.run();
assertThat(createStatus).isNotNull()
.returns(false, Result::hasErrors)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
public class WeaviateVersion {

// to be set according to weaviate docker image
public static final String EXPECTED_WEAVIATE_VERSION = "1.20.0";
public static final String EXPECTED_WEAVIATE_VERSION = "1.21.0-rc.1";
// to be set according to weaviate docker image
public static final String EXPECTED_WEAVIATE_GIT_HASH = "7865a4a";
public static final String EXPECTED_WEAVIATE_GIT_HASH = "b0d0063";

private WeaviateVersion() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.weaviate.client.v1.data.model.WeaviateObject;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.schema.model.Tenant;
import io.weaviate.integration.client.AssertMultiTenancy;
import io.weaviate.integration.client.WeaviateTestGenerics;
import org.junit.After;
Expand Down Expand Up @@ -59,7 +60,10 @@ public void after() {

@Test
public void shouldCreateObjects() {
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
Tenant[] tenants = new Tenant[]{
WeaviateTestGenerics.TENANT_1,
WeaviateTestGenerics.TENANT_2,
};
testGenerics.createSchemaPizzaForTenants(client);
testGenerics.createSchemaSoupForTenants(client);
testGenerics.createTenantsPizza(client, tenants);
Expand Down Expand Up @@ -100,28 +104,28 @@ public void shouldCreateObjects() {
.id(WeaviateTestGenerics.PIZZA_QUATTRO_FORMAGGI_ID)
.className("Pizza")
.properties(propsQuatroFormaggi)
.tenant(tenant)
.tenant(tenant.getName())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this a breaking change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope. those are only changes in test fixtures.

.build();

WeaviateObject pizzaFruttiDiMare = WeaviateObject.builder()
.id(WeaviateTestGenerics.PIZZA_FRUTTI_DI_MARE_ID)
.className("Pizza")
.properties(propsFruttiDiMare)
.tenant(tenant)
.tenant(tenant.getName())
.build();

WeaviateObject soupChicken = WeaviateObject.builder()
.id(WeaviateTestGenerics.SOUP_CHICKENSOUP_ID)
.className("Soup")
.properties(propsChicken)
.tenant(tenant)
.tenant(tenant.getName())
.build();

WeaviateObject soupBeautiful = WeaviateObject.builder()
.id(WeaviateTestGenerics.SOUP_BEAUTIFUL_ID)
.className("Soup")
.properties(propsBeautiful)
.tenant(tenant)
.tenant(tenant.getName())
.build();

return Stream.of(pizzaQuatroFormaggi, pizzaFruttiDiMare, soupChicken, soupBeautiful);
Expand All @@ -139,14 +143,14 @@ public void shouldCreateObjects() {
Map<String, List<ObjectGetResponse>> grouped = Arrays.stream(result.getResult())
.collect(Collectors.groupingBy(ObjectGetResponse::getTenant));
Arrays.stream(tenants).forEach(tenant -> {
assertThat(grouped.get(tenant)).isNotNull()
assertThat(grouped.get(tenant.getName())).isNotNull()
.hasSize(4)
.extracting(ObjectGetResponse::getId)
.containsExactlyInAnyOrderElementsOf(ids.keySet());

grouped.get(tenant).forEach(item ->
grouped.get(tenant.getName()).forEach(item ->
assertThat(item).isNotNull()
.returns(tenant, ObjectGetResponse::getTenant)
.returns(tenant.getName(), ObjectGetResponse::getTenant)
.extracting(ObjectGetResponse::getResult)
.returns(ObjectGetResponseStatus.SUCCESS, ObjectsGetResponseAO2Result::getStatus)
);
Expand All @@ -155,14 +159,17 @@ public void shouldCreateObjects() {
// verify created
Arrays.stream(tenants).forEach(tenant ->
ids.forEach((id, className) ->
assertMT.objectExists(className, id, tenant)
assertMT.objectExists(className, id, tenant.getName())
)
);
}

@Test
public void shouldNotCreateObjectsWithoutTenant() {
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
Tenant[] tenants = new Tenant[]{
WeaviateTestGenerics.TENANT_1,
WeaviateTestGenerics.TENANT_2,
};
testGenerics.createSchemaPizzaForTenants(client);
testGenerics.createSchemaSoupForTenants(client);
testGenerics.createTenantsPizza(client, tenants);
Expand Down Expand Up @@ -243,23 +250,27 @@ public void shouldNotCreateObjectsWithoutTenant() {
// verify not created
Arrays.stream(tenants).forEach(tenant ->
ids.forEach((id, className) ->
assertMT.objectDoesNotExist(className, id, tenant)
assertMT.objectDoesNotExist(className, id, tenant.getName())
)
);
}

@Test
public void shouldDeleteObjects() {
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
Tenant[] tenants = new Tenant[]{
WeaviateTestGenerics.TENANT_1,
WeaviateTestGenerics.TENANT_2,
};
String[] tenantNames = Arrays.stream(tenants).map(Tenant::getName).toArray(String[]::new);
testGenerics.createSchemaFoodForTenants(client);
testGenerics.createTenantsFood(client, tenants);
testGenerics.createDataFoodForTenants(client, tenants);
testGenerics.createDataFoodForTenants(client, tenantNames);

Arrays.stream(tenants).forEach(tenant ->
WeaviateTestGenerics.IDS_BY_CLASS.forEach((className, ids) -> {
Result<BatchDeleteResponse> result = client.batch().objectsBatchDeleter()
.withClassName(className)
.withTenant(tenant)
.withTenant(tenant.getName())
.withWhere(WhereFilter.builder()
.operator(Operator.Like)
.path(new String[]{"_id"})
Expand All @@ -275,17 +286,21 @@ public void shouldDeleteObjects() {
.returns((long) ids.size(), BatchDeleteResponse.Results::getSuccessful);

// verify deleted
ids.forEach(id -> assertMT.objectDoesNotExist(className, id, tenant));
ids.forEach(id -> assertMT.objectDoesNotExist(className, id, tenant.getName()));
})
);
}

@Test
public void shouldNotDeleteObjectsWithoutTenant() {
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
Tenant[] tenants = new Tenant[]{
WeaviateTestGenerics.TENANT_1,
WeaviateTestGenerics.TENANT_2,
};
String[] tenantNames = Arrays.stream(tenants).map(Tenant::getName).toArray(String[]::new);
testGenerics.createSchemaFoodForTenants(client);
testGenerics.createTenantsFood(client, tenants);
testGenerics.createDataFoodForTenants(client, tenants);
testGenerics.createDataFoodForTenants(client, tenantNames);

WeaviateTestGenerics.IDS_BY_CLASS.forEach((className, ids) -> {
Result<BatchDeleteResponse> result = client.batch().objectsBatchDeleter()
Expand All @@ -302,7 +317,7 @@ public void shouldNotDeleteObjectsWithoutTenant() {

Arrays.stream(tenants).forEach(tenant ->
WeaviateTestGenerics.IDS_BY_CLASS.forEach((className, ids) ->
ids.forEach(id -> assertMT.objectExists(className, id, tenant))
ids.forEach(id -> assertMT.objectExists(className, id, tenant.getName()))
)
);
}
Expand Down
Loading