Skip to content

Commit

Permalink
add metadata api (#947)
Browse files Browse the repository at this point in the history
* feat: add metadata api
Signed-off-by: saberwang <saberwang@hotmail.com>

* Using HTTP API to get and set dapr metadata
Signed-off-by: saberwang <saberwang@hotmail.com>

* style
Signed-off-by: saberwang <saberwang@hotmail.com>

* using grpc to add metadata api
Signed-off-by: saberwang <saberwang@hotmail.com>

* style
Signed-off-by: saberwang <saberwang@hotmail.com>

Co-authored-by: halspang <70976921+halspang@users.noreply.github.com>
  • Loading branch information
saber-wang and halspang authored Sep 23, 2022
1 parent 37ed498 commit 01cdc89
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 20 deletions.
32 changes: 31 additions & 1 deletion src/Dapr.Client/DaprClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -338,6 +338,36 @@ public HttpRequestMessage CreateInvokeMethodRequest<TRequest>(string appId, stri
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public abstract Task ShutdownSidecarAsync(CancellationToken cancellationToken = default);

/// <summary>
/// Calls the sidecar's metadata endpoint which returns information including:
/// <list type="bullet">
/// <item>
/// <description>The sidecar's ID.</description>
/// </item>
/// <item>
/// <description>The registered/active actors if any.</description>
/// </item>
/// <item>
/// <description>Registered components including name, type, version, and information on capabilities if present.</description>
/// </item>
/// <item>
/// <description>Any extended metadata that has been set via <see cref="SetMetadataAsync"/></description>
/// </item>
/// </list>
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<DaprMetadata> GetMetadataAsync(CancellationToken cancellationToken = default);

/// <summary>
/// Perform service add extended metadata to the Dapr sidecar.
/// </summary>
/// <param name="attributeName">Custom attribute name</param>
/// <param name="attributeValue">Custom attribute value</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return the value when the operation has completed.</returns>
public abstract Task SetMetadataAsync(string attributeName, string attributeValue, CancellationToken cancellationToken = default);

/// <summary>
/// Perform service invocation using the request provided by <paramref name="request" />. The response will
/// be returned without performing any validation on the status code.
Expand Down
40 changes: 40 additions & 0 deletions src/Dapr.Client/DaprClientGrpc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,46 @@ public async override Task ShutdownSidecarAsync(CancellationToken cancellationTo
await client.ShutdownAsync(new Empty(), CreateCallOptions(null, cancellationToken));
}

/// <inheritdoc/>
public override async Task<DaprMetadata> GetMetadataAsync(CancellationToken cancellationToken = default)
{
var options = CreateCallOptions(headers: null, cancellationToken);
try
{
var response = await client.GetMetadataAsync(new Empty(), options);
return new DaprMetadata(response.Id,
response.ActiveActorsCount.Select(c => new DaprActorMetadata(c.Type, c.Count)).ToList(),
response.ExtendedMetadata.ToDictionary(c => c.Key, c => c.Value),
response.RegisteredComponents.Select(c => new DaprComponentsMetadata(c.Name, c.Type, c.Version, c.Capabilities.ToArray())).ToList());
}
catch (RpcException ex)
{
throw new DaprException("Get metadata operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
}
}

/// <inheritdoc/>
public override async Task SetMetadataAsync(string attributeName, string attributeValue, CancellationToken cancellationToken = default)
{
ArgumentVerifier.ThrowIfNullOrEmpty(attributeName, nameof(attributeName));

var envelope = new Autogenerated.SetMetadataRequest()
{
Key = attributeName,
Value = attributeValue
};

var options = CreateCallOptions(headers: null, cancellationToken);

try
{
_ = await this.Client.SetMetadataAsync(envelope, options);
}
catch (RpcException ex)
{
throw new DaprException("Set metadata operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
}
}
#endregion

protected override void Dispose(bool disposing)
Expand Down
126 changes: 126 additions & 0 deletions src/Dapr.Client/DaprMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------

using System.Collections.Generic;

namespace Dapr.Client
{
/// <summary>
/// Represents a metadata object returned from dapr sidecar.
/// </summary>
public sealed class DaprMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="DaprMetadata"/> class.
/// </summary>
/// <param name="id">The application id.</param>
/// <param name="actors">The registered actors metadata.</param>
/// <param name="extended">The list of custom attributes as key-value pairs, where key is the attribute name.</param>
/// <param name="components">The loaded components metadata.</param>
public DaprMetadata(string id, IReadOnlyList<DaprActorMetadata> actors, IReadOnlyDictionary<string, string> extended, IReadOnlyList<DaprComponentsMetadata> components)
{
Id = id;
Actors = actors;
Extended = extended;
Components = components;
}

/// <summary>
/// Gets the application id.
/// </summary>
public string Id { get; }

/// <summary>
/// Gets the registered actors metadata.
/// </summary>
public IReadOnlyList<DaprActorMetadata> Actors { get; }

/// <summary>
/// Gets the list of custom attributes as key-value pairs, where key is the attribute name.
/// </summary>
public IReadOnlyDictionary<string, string> Extended { get; }

/// <summary>
/// Gets the loaded components metadata.
/// </summary>
public IReadOnlyList<DaprComponentsMetadata> Components { get; }
}

/// <summary>
/// Represents a actor metadata object returned from dapr sidecar.
/// </summary>
public sealed class DaprActorMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="DaprActorMetadata"/> class.
/// </summary>
/// <param name="type">This registered actor type.</param>
/// <param name="count">The number of actors running.</param>
public DaprActorMetadata(string type, int count)
{
Type = type;
Count = count;
}

/// <summary>
/// Gets the registered actor type.
/// </summary>
public string Type { get; }

/// <summary>
/// Gets the number of actors running.
/// </summary>
public int Count { get; }
}

/// <summary>
/// Represents a components metadata object returned from dapr sidecar.
/// </summary>
public sealed class DaprComponentsMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="DaprComponentsMetadata"/> class.
/// </summary>
/// <param name="name">The name of the component.</param>
/// <param name="type">The component type.</param>
/// <param name="version">The component version.</param>
/// <param name="capabilities">The supported capabilities for this component type and version.</param>
public DaprComponentsMetadata(string name, string type, string version, string[] capabilities)
{
Name = name;
Type = type;
Version = version;
Capabilities = capabilities;
}

/// <summary>
/// Gets the name of the component.
/// </summary>
public string Name { get; }

/// <summary>
/// Gets the component type.
/// </summary>
public string Type { get; }

/// <summary>
/// Gets the component version.
/// </summary>
public string Version { get; }

/// <summary>
/// Gets the supported capabilities for this component type and version.
/// </summary>
public string[] Capabilities { get; }
}
}
4 changes: 3 additions & 1 deletion test/Dapr.Client.Test/DaprClientTest.InvokeMethodAsync.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -14,6 +14,7 @@
namespace Dapr.Client.Test
{
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
Expand All @@ -22,6 +23,7 @@ namespace Dapr.Client.Test
using System.Threading;
using System.Threading.Tasks;
using Dapr.Client;
using FluentAssertions;
using Xunit;

// Most of the InvokeMethodAsync functionality on DaprClient is non-abstract methods that
Expand Down
Loading

0 comments on commit 01cdc89

Please sign in to comment.