Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ on:
- beta
- master
- staging
- mlh-1226-denorm-attrs-push-kafka
Copy link

Choose a reason for hiding this comment

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

Bug: CI Workflow Contains Hardcoded Feature Branch Trigger

The CI workflow includes a hardcoded trigger for the mlh-1226-denorm-attrs-push-kafka feature branch. This appears to be temporary testing configuration that was committed inadvertently, as feature branch names are typically not hardcoded in shared CI workflows.

Fix in Cursor Fix in Web


jobs:
build:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@

import java.util.*;

import org.apache.atlas.RequestContext;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasElement;
import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.graphdb.janus.graphson.AtlasGraphSONMode;
import org.apache.atlas.repository.graphdb.janus.graphson.AtlasGraphSONUtility;
import org.apache.commons.lang.StringUtils;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.codehaus.jettison.json.JSONException;
Expand All @@ -35,6 +37,9 @@
import org.janusgraph.core.SchemaViolationException;
import org.janusgraph.core.JanusGraphElement;

import static org.apache.atlas.type.Constants.GUID_PROPERTY_KEY;
import static org.apache.atlas.type.Constants.INTERNAL_PROPERTY_KEY_PREFIX;

/**
* Janus implementation of AtlasElement.
*
Expand Down Expand Up @@ -109,36 +114,49 @@ public void removeProperty(String propertyName) {
while(it.hasNext()) {
Property<String> property = it.next();
property.remove();
recordInternalAttribute(propertyName, null);
Copy link

Choose a reason for hiding this comment

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

Bug: Inconsistent Property Removal Logging

The removeProperty method repeatedly calls recordInternalAttribute within its loop for each property value removed. This creates unnecessary overhead and is inconsistent with other remove methods that record the final state once.

Fix in Cursor Fix in Web

}
}

@Override
public void removePropertyValue(String propertyName, Object propertyValue) {
Iterator<? extends Property<Object>> it = getWrappedElement().properties(propertyName);
List<Object> finalValues = new ArrayList<>();
boolean removedFirst = false;

while (it.hasNext()) {
Property currentProperty = it.next();
Object currentPropertyValue = currentProperty.value();

if (Objects.equals(currentPropertyValue, propertyValue)) {
if (!removedFirst && Objects.equals(currentPropertyValue, propertyValue)) {
currentProperty.remove();
break;
removedFirst = true;
} else {
finalValues.add(currentPropertyValue);
}
}

recordInternalAttribute(propertyName, finalValues);
Copy link

Choose a reason for hiding this comment

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

Bug: Property Removal Causes Incorrect Context Updates

The removeProperty method calls recordInternalAttribute repeatedly within a loop, which can lead to incorrect RequestContext updates. Separately, removePropertyValue and removeAllPropertyValue modify the underlying collection during iteration, potentially causing ConcurrentModificationException.

Fix in Cursor Fix in Web

}

@Override
public void removeAllPropertyValue(String propertyName, Object propertyValue) {
Iterator<? extends Property<Object>> it = getWrappedElement().properties(propertyName);
List<Object> finalValues = new ArrayList<>();


while (it.hasNext()) {
Property currentProperty = it.next();
Object currentPropertyValue = currentProperty.value();

if (Objects.equals(currentPropertyValue, propertyValue)) {
currentProperty.remove();
} else {
finalValues.add(currentPropertyValue);
}
}

recordInternalAttribute(propertyName, finalValues);
}

@Override
Expand All @@ -151,6 +169,7 @@ public void setProperty(String propertyName, Object value) {
}
} else {
getWrappedElement().property(propertyName, value);
recordInternalAttribute(propertyName, value);
}
} catch(SchemaViolationException e) {
throw new AtlasSchemaViolationException(e);
Expand Down Expand Up @@ -308,7 +327,6 @@ public void setPropertyFromElementsIds(String propertyName, List<AtlasElement> v
@Override
public void setPropertyFromElementId(String propertyName, AtlasElement value) {
setProperty(propertyName, value.getId().toString());

}


Expand All @@ -317,4 +335,20 @@ public boolean isIdAssigned() {
return true;
}

private void recordInternalAttribute(String propertyName, Object finalValue) {
if (propertyName.startsWith(INTERNAL_PROPERTY_KEY_PREFIX)) {
RequestContext context = RequestContext.get();
String entityGuid = this.getProperty(GUID_PROPERTY_KEY, String.class);

if (StringUtils.isNotEmpty(entityGuid)) {
if (context.getAllInternalAttributesMap().get(entityGuid) != null) {
context.getAllInternalAttributesMap().get(entityGuid).put(propertyName, finalValue);
} else {
Map<String, Object> map = new HashMap<>();
map.put(propertyName, finalValue);
context.getAllInternalAttributesMap().put(entityGuid, map);
}
}
}
}
}
6 changes: 6 additions & 0 deletions server-api/src/main/java/org/apache/atlas/RequestContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class RequestContext {
private final Map<String, AtlasEntityHeader> updatedEntities = new HashMap<>();
private final Map<String, AtlasEntityHeader> deletedEntities = new HashMap<>();
private final Map<String, AtlasEntityHeader> restoreEntities = new HashMap<>();
private final Map<String, Map<String, Object>> allInternalAttributesMap = new HashMap<>();


private Map<String, String> lexoRankCache = null;
Expand Down Expand Up @@ -200,6 +201,7 @@ public void clearCache() {
addedClassificationAndVertices.clear();
esDeferredOperations.clear();
this.cassandraTagOperations.clear();
this.allInternalAttributesMap.clear();

if (metrics != null && !metrics.isEmpty()) {
METRICS.debug(metrics.toString());
Expand Down Expand Up @@ -877,6 +879,10 @@ public boolean isInvokedByLineage() {
return isInvokedByLineage;
}

public Map<String, Map<String, Object>> getAllInternalAttributesMap() {
return allInternalAttributesMap;
}

public class EntityGuidPair {
private final Object entity;
private final String guid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,16 @@ private AtlasEntityHeaderWithRelations toNotificationHeader(AtlasEntity entity)
}
}

// fill the internal properties like __glossary, __meanings etc. (ES Isolation)
RequestContext context = RequestContext.get();
Map<String, Object> allInternalAttributesMap = context.getAllInternalAttributesMap().get(entity.getGuid());
if (MapUtils.isNotEmpty(allInternalAttributesMap)) {
for (String key : allInternalAttributesMap.keySet()) {
Object value = allInternalAttributesMap.get(key);
ret.setAttribute(key, value);

Choose a reason for hiding this comment

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

this will put internal attributes in attributes like attributes.__meanings. Nothing wrong in this just wanted to highlight

}
}

//Add relationship attributes which has isOptional as false
Map<String, Object> rel = new HashMap<>();
for (Map<String, AtlasAttribute> attrs : entityType.getRelationshipAttributes().values()) {
Expand Down
Loading