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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
Copy link
Member

Choose a reason for hiding this comment

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

We should fix isDuplicateKey function, Existing labels , id should be used to find duplicates, and then name should be unique. We need to fix this

import java.util.stream.Collectors;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -52,7 +53,6 @@ public class LabelsConfigServiceImpl extends LabelsConfigServiceGrpc.LabelsConfi
private final LabelStore labelStore;
private final List<Label> systemLabels;
private final Map<String, Label> systemLabelsIdLabelMap;
private final Map<String, Label> systemLabelsKeyLabelMap;

public LabelsConfigServiceImpl(
Channel configChannel, Config config, ConfigChangeEventGenerator configChangeEventGenerator) {
Expand All @@ -74,13 +74,9 @@ public LabelsConfigServiceImpl(
systemLabels = buildSystemLabelList(systemLabelsObjectList);
systemLabelsIdLabelMap =
systemLabels.stream().collect(Collectors.toUnmodifiableMap(Label::getId, identity()));
systemLabelsKeyLabelMap =
systemLabels.stream()
.collect(Collectors.toUnmodifiableMap(label -> label.getData().getKey(), identity()));
} else {
systemLabels = Collections.emptyList();
systemLabelsIdLabelMap = Collections.emptyMap();
systemLabelsKeyLabelMap = Collections.emptyMap();
}
}

Expand Down Expand Up @@ -194,15 +190,13 @@ public void getLabel(GetLabelRequest request, StreamObserver<GetLabelResponse> r
RequestContext requestContext = RequestContext.CURRENT.get();
String labelId = request.getId();
try {
Label label;
Copy link
Member

Choose a reason for hiding this comment

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

You would need to make changes in almost all the methods available in this api. So the flow would be like this

  1. We will build the defaultLabels list from the config.
  2. Now any update request can come from Clients. If update is for a label with id from system labels, then you save the entry in Db after doing necessary validation. For example we might not want to update names for system labels. Add necessary validation wherever needed.
  3. In case of read, We need to merge DB based labels and system labels while giving priority to DB entry and reorder if necessary. For example we always generally wants system label to be at the end of the list

if (systemLabelsIdLabelMap.containsKey(labelId)) {
label = systemLabelsIdLabelMap.get(labelId);
} else {
label =
labelStore
.getData(requestContext, labelId)
.orElseThrow(Status.NOT_FOUND::asRuntimeException);
}
Label label =
labelStore
.getData(requestContext, labelId)
.orElseGet(
() ->
Optional.ofNullable(systemLabelsIdLabelMap.get(labelId))
.orElseThrow(Status.NOT_FOUND::asRuntimeException));
responseObserver.onNext(GetLabelResponse.newBuilder().setLabel(label).build());
responseObserver.onCompleted();
} catch (Exception e) {
Expand All @@ -214,12 +208,17 @@ public void getLabel(GetLabelRequest request, StreamObserver<GetLabelResponse> r
public void getLabels(
GetLabelsRequest request, StreamObserver<GetLabelsResponse> responseObserver) {
RequestContext requestContext = RequestContext.CURRENT.get();
List<Label> allLabels = new ArrayList<>(systemLabels);
List<Label> tenantLabels =
labelStore.getAllObjects(requestContext).stream()
.map(ContextualConfigObject::getData)
.collect(Collectors.toUnmodifiableList());
allLabels.addAll(tenantLabels);
Map<String, Label> tenantLabelsMap =
tenantLabels.stream()
.collect(Collectors.toUnmodifiableMap(Label::getId, Function.identity()));
List<Label> allLabels = new ArrayList<>(tenantLabels);
systemLabels.stream()
.filter(label -> !tenantLabelsMap.containsKey(label.getId()))
.forEach(allLabels::add);
responseObserver.onNext(GetLabelsResponse.newBuilder().addAllLabels(allLabels).build());
responseObserver.onCompleted();
}
Expand All @@ -230,19 +229,18 @@ public void updateLabel(
try {
LabelData updateLabelData = request.getData();
RequestContext requestContext = RequestContext.CURRENT.get();
if (systemLabelsIdLabelMap.containsKey(request.getId())) {
// Updating a system label will error
responseObserver.onError(new StatusRuntimeException(Status.INVALID_ARGUMENT));
return;
}

if (isDuplicateKey(requestContext, request.getId(), updateLabelData.getKey())) {
responseObserver.onError(new StatusRuntimeException(Status.ALREADY_EXISTS));
return;
}
Label oldLabel =
labelStore
.getData(requestContext, request.getId())
.orElseThrow(Status.NOT_FOUND::asRuntimeException);
.orElseGet(
() ->
Optional.ofNullable(systemLabelsIdLabelMap.get(request.getId()))
.orElseThrow(Status.NOT_FOUND::asRuntimeException));
Label updateLabel = oldLabel.toBuilder().setData(updateLabelData).build();
Label updateLabelInRes = labelStore.upsertObject(requestContext, updateLabel).getData();
responseObserver.onNext(UpdateLabelResponse.newBuilder().setLabel(updateLabelInRes).build());
Expand Down Expand Up @@ -284,10 +282,11 @@ private boolean isDuplicateKey(RequestContext requestContext, String key) {
}

private Map<String, Label> getLabelsMap(RequestContext requestContext) {
Map<String, Label> existingLabelsMap = new HashMap<>(systemLabelsKeyLabelMap);
Map<String, Label> mergedLabels = new HashMap<>(systemLabelsIdLabelMap);
labelStore.getAllObjects(requestContext).stream()
.map(ContextualConfigObject::getData)
.forEach(label -> existingLabelsMap.put(label.getData().getKey(), label));
return Collections.unmodifiableMap(existingLabelsMap);
.forEach(label -> mergedLabels.put(label.getId(), label));
return mergedLabels.values().stream()
.collect(Collectors.toUnmodifiableMap(label -> label.getData().getKey(), identity()));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.hypertrace.label.config.service;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -329,25 +330,22 @@ void test_updateLabel() {
@Test
void test_system_updateLabel() {
List<Label> createdLabelsList = createLabels();
// updating system label key, should not throw error.
for (Label systemLabel : systemLabels) {
UpdateLabelRequest updateLabelRequest =
UpdateLabelRequest.newBuilder()
.setId(systemLabel.getId())
.setData(LabelData.newBuilder().setKey("1").build())
.setData(LabelData.newBuilder().setKey(systemLabel.getData().getKey() + "_1").build())
.build();
Throwable exception =
assertThrows(
StatusRuntimeException.class,
() -> {
labelConfigStub.updateLabel(updateLabelRequest);
});
assertEquals(Status.INVALID_ARGUMENT, Status.fromThrowable(exception));
assertDoesNotThrow(() -> labelConfigStub.updateLabel(updateLabelRequest));
Copy link
Member

Choose a reason for hiding this comment

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

this test case is wrong. we should add necessary validations

}

// updating existing label with updated system label key, should throw error.
for (Label systemLabel : systemLabels) {
UpdateLabelRequest updateLabelRequest =
UpdateLabelRequest.newBuilder()
.setId(createdLabelsList.get(0).getId())
.setData(LabelData.newBuilder().setKey(systemLabel.getData().getKey()).build())
.setData(LabelData.newBuilder().setKey(systemLabel.getData().getKey() + "_1").build())
.build();
Throwable exception =
assertThrows(
Expand All @@ -357,6 +355,16 @@ void test_system_updateLabel() {
});
assertEquals(Status.ALREADY_EXISTS, Status.fromThrowable(exception));
}

// updating existing label with system label keys present in config, should not throw error.
for (Label systemLabel : systemLabels) {
UpdateLabelRequest updateLabelRequest =
UpdateLabelRequest.newBuilder()
.setId(createdLabelsList.get(0).getId())
.setData(LabelData.newBuilder().setKey(systemLabel.getData().getKey()).build())
.build();
assertDoesNotThrow(() -> labelConfigStub.updateLabel(updateLabelRequest));
}
}

@Test
Expand Down
Loading