use of org.hypertrace.entity.data.service.v1.Entity.Builder in project entity-service by hypertrace.
the class EntityDataServiceImpl method getAndUpsertEntities.
@Override
public void getAndUpsertEntities(Entities request, StreamObserver<Entity> responseObserver) {
String tenantId = RequestContext.CURRENT.get().getTenantId().orElse(null);
if (tenantId == null) {
responseObserver.onError(new ServiceException("Tenant id is missing in the request."));
return;
}
try {
Map<Key, Document> documentMap = new HashMap<>();
List<Entity> updatedEntities = new ArrayList<>();
for (Entity entity : request.getEntityList()) {
Entity normalizedEntity = this.entityNormalizer.normalize(tenantId, entity);
updatedEntities.add(normalizedEntity);
Document doc = convertEntityToDocument(normalizedEntity);
Key key = this.entityNormalizer.getEntityDocKey(tenantId, normalizedEntity);
documentMap.put(key, doc);
}
List<Entity> existingEntities = Streams.stream(entitiesCollection.bulkUpsertAndReturnOlderDocuments(documentMap)).flatMap(document -> PARSER.<Entity>parseOrLog(document, Entity.newBuilder()).stream()).map(Entity::toBuilder).map(builder -> builder.setTenantId(tenantId)).map(Entity.Builder::build).collect(Collectors.toList());
existingEntities.forEach(responseObserver::onNext);
responseObserver.onCompleted();
entityChangeEventGenerator.sendChangeNotification(RequestContext.CURRENT.get(), existingEntities, updatedEntities);
} catch (IOException e) {
LOG.error("Failed to bulk upsert entities", e);
responseObserver.onError(e);
}
}
use of org.hypertrace.entity.data.service.v1.Entity.Builder in project entity-service by hypertrace.
the class EntityDataServiceImpl method mergeAndUpsertEntity.
@Override
public void mergeAndUpsertEntity(MergeAndUpsertEntityRequest request, StreamObserver<MergeAndUpsertEntityResponse> responseObserver) {
RequestContext requestContext = RequestContext.CURRENT.get();
String tenantId = requestContext.getTenantId().orElse(null);
if (tenantId == null) {
responseObserver.onError(new ServiceException("Tenant id is missing in the request."));
return;
}
Entity receivedEntity = this.entityNormalizer.normalize(tenantId, request.getEntity());
Optional<Entity> existingEntity = getExistingEntity(tenantId, receivedEntity.getEntityType(), receivedEntity.getEntityId());
boolean rejectUpsertForConditionMismatch = existingEntity.map(entity -> !this.upsertConditionMatcher.matches(entity, request.getUpsertCondition())).orElse(false);
if (rejectUpsertForConditionMismatch) {
// There's an existing entity and the update doesn't meet the condition, return existing
responseObserver.onNext(MergeAndUpsertEntityResponse.newBuilder().setEntity(existingEntity.get()).build());
responseObserver.onCompleted();
} else {
// There's either a new entity or a valid update to upsert
Entity entityToUpsert = existingEntity.map(Entity::toBuilder).map(Entity.Builder::clearCreatedTime).map(builder -> builder.mergeFrom(receivedEntity)).map(Builder::build).orElse(receivedEntity);
try {
Entity upsertedEntity = this.upsertEntity(tenantId, entityToUpsert);
responseObserver.onNext(MergeAndUpsertEntityResponse.newBuilder().setEntity(upsertedEntity).build());
responseObserver.onCompleted();
entityChangeEventGenerator.sendChangeNotification(requestContext, existingEntity.map(List::of).orElse(Collections.emptyList()), List.of(upsertedEntity));
} catch (IOException e) {
responseObserver.onError(e);
}
}
}
use of org.hypertrace.entity.data.service.v1.Entity.Builder in project entity-service by hypertrace.
the class EntityDataServiceImpl method searchByIdAndStreamSingleResponse.
private <T extends Message> void searchByIdAndStreamSingleResponse(String tenantId, String entityId, String entityType, Collection collection, Message.Builder builder, StreamObserver<T> responseObserver) {
org.hypertrace.core.documentstore.Query query = new org.hypertrace.core.documentstore.Query();
String docId = this.entityNormalizer.getEntityDocKey(tenantId, entityType, entityId).toString();
query.setFilter(new Filter(Filter.Op.EQ, EntityServiceConstants.ID, docId));
Iterator<Document> result = collection.search(query);
List<T> entities = new ArrayList<>();
while (result.hasNext()) {
PARSER.<T>parseOrLog(result.next(), builder.clone()).map(entity -> {
// Populate the tenant id field with the tenant id that's received for backward
// compatibility.
Descriptors.FieldDescriptor fieldDescriptor = entity.getDescriptorForType().findFieldByName("tenant_id");
if (fieldDescriptor != null) {
return (T) entity.toBuilder().setField(fieldDescriptor, tenantId).build();
}
return entity;
}).ifPresent(entities::add);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Docstore query has returned the result: {}", entities);
}
if (entities.size() == 1) {
responseObserver.onNext(entities.get(0));
responseObserver.onCompleted();
} else if (entities.size() > 1) {
responseObserver.onError(new IllegalStateException("Multiple entities with same id are found."));
} else {
// When there is no result, we should return the default instance, which is a way
// of saying it's null.
// TODO : Not convinced with the default instance
responseObserver.onNext((T) builder.build());
responseObserver.onCompleted();
}
}
use of org.hypertrace.entity.data.service.v1.Entity.Builder in project entity-service by hypertrace.
the class EntityDataServiceTest method testUpdateEntityViaUpsertAndMerge.
@Test
public void testUpdateEntityViaUpsertAndMerge() {
// Scope this test to its own tenant for isolation
String TENANT_ID = EntityDataServiceTest.TENANT_ID + "_testUpdateEntityViaUpsertAndMerge";
EntityDataServiceBlockingStub entityDataServiceStub = buildStubForTenant(TENANT_ID);
setupEntityTypes(channel, TENANT_ID);
Map<String, AttributeValue> createAttributes = Map.of("some-attr", stringValue("v1"));
Map<String, AttributeValue> updateAttributes = Map.of("some-other-attr", stringValue("v2"));
// V1 entity
Entity entityToCreate = Entity.newBuilder().setTenantId(TENANT_ID).setEntityType(EntityType.K8S_POD.name()).setEntityName("V1 UPDATE POD").putIdentifyingAttributes(EntityConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_EXTERNAL_ID), generateRandomUUIDAttrValue()).putAllAttributes(createAttributes).build();
entityDataServiceStub.mergeAndUpsertEntity(MergeAndUpsertEntityRequest.newBuilder().setEntity(entityToCreate).build());
Entity entityUpdate = entityToCreate.toBuilder().clearAttributes().putAllAttributes(updateAttributes).build();
Entity updatedEntity = entityDataServiceStub.mergeAndUpsertEntity(MergeAndUpsertEntityRequest.newBuilder().setEntity(entityUpdate).build()).getEntity();
Map<String, AttributeValue> combinedAttributes = ImmutableMap.<String, AttributeValue>builder().putAll(createAttributes).putAll(entityToCreate.getIdentifyingAttributesMap()).putAll(updateAttributes).build();
assertEquals(combinedAttributes, updatedEntity.getAttributesMap());
// V2 Entity
entityToCreate = Entity.newBuilder().setTenantId(TENANT_ID).setEntityId(UUID.randomUUID().toString()).setEntityType(TEST_ENTITY_TYPE_V2).setEntityName("V2 entity update").putAllAttributes(createAttributes).build();
entityDataServiceStub.mergeAndUpsertEntity(MergeAndUpsertEntityRequest.newBuilder().setEntity(entityToCreate).build());
entityUpdate = entityToCreate.toBuilder().clearAttributes().putAllAttributes(updateAttributes).build();
updatedEntity = entityDataServiceStub.mergeAndUpsertEntity(MergeAndUpsertEntityRequest.newBuilder().setEntity(entityUpdate).build()).getEntity();
combinedAttributes = ImmutableMap.<String, AttributeValue>builder().putAll(createAttributes).putAll(updateAttributes).build();
assertEntityEquals(entityToCreate.toBuilder().clearAttributes().putAllAttributes(combinedAttributes).build(), updatedEntity);
}
Aggregations