Skip to content

Commit

Permalink
Add XdsDirectory to get d2 service and cluster names from INDIS (#1038)
Browse files Browse the repository at this point in the history
* Add XdsDirectory to get d2 service and cluster names from INDIS

* add D2ClusterOrServiceName proto, wrap subscriber map in getter for testing

* wait until all changes to names complete before serving

* add and update XdsClient tests

* add XdsDirectory tests

* cleanups

* check string non-null and non-empty in the directory

* call onAllResourcesProcessed when received the last response chunk, and unlock write lock after checking isUpdating flag

* update doc

* change back to object lock to be able to unlock from another thread

* touch up

* touch up

* also notify all resources processed when failed to parse nonce

* add default timeout

* handle interruption explicitly

* use rate limitted logger for nonce parsing failure

* set logger rate to 10s

* set logger rate to 1min

* test calling onAllResourcesProcessed from a separate thread

* use count down latch in test for stableness
  • Loading branch information
bohhyang authored Jan 30, 2025
1 parent 1eeec25 commit b2da251
Show file tree
Hide file tree
Showing 10 changed files with 1,165 additions and 291 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and what APIs have changed, if applicable.

## [Unreleased]

## [29.63.1] - 2025-01-14
- Add XdsDirectory to get d2 service and cluster names from INDIS

## [29.63.0] - 2024-11-06
- Add announcer status delegate interface

Expand Down Expand Up @@ -5761,7 +5764,8 @@ patch operations can re-use these classes for generating patch messages.

## [0.14.1]

[Unreleased]: https://github.com/linkedin/rest.li/compare/v29.63.0...master
[Unreleased]: https://github.com/linkedin/rest.li/compare/v29.63.1...master
[29.63.1]: https://github.com/linkedin/rest.li/compare/v29.63.0...v29.63.1
[29.63.0]: https://github.com/linkedin/rest.li/compare/v29.62.1...v29.63.0
[29.62.1]: https://github.com/linkedin/rest.li/compare/v29.62.0...v29.62.1
[29.62.0]: https://github.com/linkedin/rest.li/compare/v29.61.0...v29.62.0
Expand Down
87 changes: 86 additions & 1 deletion d2/src/main/java/com/linkedin/d2/xds/XdsClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.linkedin.d2.xds;

import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.linkedin.d2.jmx.XdsClientJmx;
import indis.XdsD2;
import io.grpc.Status;
Expand Down Expand Up @@ -135,6 +136,16 @@ final ResourceType getType()
* @param resourceName the name of the resource that was removed.
*/
public abstract void onRemoval(String resourceName);

/**
* Just a signal to notify that all resources (including both changed and removed ones) in all response chunks (if
* any) have been processed.
* Default implementation does nothing.
*/
public void onAllResourcesProcessed()
{
// do nothing
}
}

public static abstract class WildcardNodeResourceWatcher extends WildcardResourceWatcher
Expand Down Expand Up @@ -180,6 +191,27 @@ final void onChanged(String resourceName, ResourceUpdate update)
}
}

public static abstract class WildcardD2ClusterOrServiceNameResourceWatcher extends WildcardResourceWatcher
{
public WildcardD2ClusterOrServiceNameResourceWatcher()
{
super(ResourceType.D2_CLUSTER_OR_SERVICE_NAME);
}

/**
* Called when a D2ClusterOrServiceName resource is added or updated.
* @param resourceName the resource name of the D2ClusterOrServiceName that was added or updated.
* @param update the new data for the D2ClusterOrServiceName resource
*/
public abstract void onChanged(String resourceName, D2ClusterOrServiceNameUpdate update);

@Override
final void onChanged(String resourceName, ResourceUpdate update)
{
onChanged(resourceName, (D2ClusterOrServiceNameUpdate) update);
}
}

public interface ResourceUpdate
{
boolean isValid();
Expand Down Expand Up @@ -233,6 +265,55 @@ public String toString()
}
}

public static final class D2ClusterOrServiceNameUpdate implements ResourceUpdate
{
XdsD2.D2ClusterOrServiceName _nameData;

D2ClusterOrServiceNameUpdate(XdsD2.D2ClusterOrServiceName nameData)
{
_nameData = nameData;
}

public XdsD2.D2ClusterOrServiceName getNameData()
{
return _nameData;
}

@Override
public boolean equals(Object object)
{
if (this == object)
{
return true;
}
if (object == null || getClass() != object.getClass())
{
return false;
}
D2ClusterOrServiceNameUpdate that = (D2ClusterOrServiceNameUpdate) object;
return Objects.equals(_nameData, that._nameData);
}

@Override
public int hashCode()
{
return Objects.hash(_nameData);
}

@Override
public boolean isValid()
{
return _nameData != null
&& (!Strings.isNullOrEmpty(_nameData.getClusterName()) || !Strings.isNullOrEmpty(_nameData.getServiceName()));
}

@Override
public String toString()
{
return MoreObjects.toStringHelper(this).add("_nameData", _nameData).toString();
}
}

public static final class D2URIMapUpdate implements ResourceUpdate
{
Map<String, XdsD2.D2URI> _uriMap;
Expand Down Expand Up @@ -302,12 +383,16 @@ public String toString()

public static final NodeUpdate EMPTY_NODE_UPDATE = new NodeUpdate(null);
public static final D2URIMapUpdate EMPTY_D2_URI_MAP_UPDATE = new D2URIMapUpdate(null);
public static final D2ClusterOrServiceNameUpdate EMPTY_D2_CLUSTER_OR_SERVICE_NAME_UPDATE =
new D2ClusterOrServiceNameUpdate(null);

enum ResourceType
{
NODE("type.googleapis.com/indis.Node", EMPTY_NODE_UPDATE),
D2_URI_MAP("type.googleapis.com/indis.D2URIMap", EMPTY_D2_URI_MAP_UPDATE),
D2_URI("type.googleapis.com/indis.D2URI", EMPTY_D2_URI_MAP_UPDATE);
D2_URI("type.googleapis.com/indis.D2URI", EMPTY_D2_URI_MAP_UPDATE),
D2_CLUSTER_OR_SERVICE_NAME("type.googleapis.com/indis.D2ClusterOrServiceName",
EMPTY_D2_CLUSTER_OR_SERVICE_NAME_UPDATE);

private static final Map<String, ResourceType> TYPE_URL_TO_ENUM = Arrays.stream(values())
.filter(e -> e.typeUrl() != null)
Expand Down
Loading

0 comments on commit b2da251

Please sign in to comment.