contracts: add BrowseChildren RPC for lazy hierarchy browse
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -67,6 +67,10 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy {
|
||||
static readonly grpc::Marshaller<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.WatchDeployEventsRequest> __Marshaller_galaxy_repository_v1_WatchDeployEventsRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.WatchDeployEventsRequest.Parser));
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
static readonly grpc::Marshaller<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.DeployEvent> __Marshaller_galaxy_repository_v1_DeployEvent = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.DeployEvent.Parser));
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
static readonly grpc::Marshaller<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest> __Marshaller_galaxy_repository_v1_BrowseChildrenRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest.Parser));
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
static readonly grpc::Marshaller<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply> __Marshaller_galaxy_repository_v1_BrowseChildrenReply = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply.Parser));
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
static readonly grpc::Method<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.TestConnectionRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.TestConnectionReply> __Method_TestConnection = new grpc::Method<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.TestConnectionRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.TestConnectionReply>(
|
||||
@@ -100,6 +104,14 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy {
|
||||
__Marshaller_galaxy_repository_v1_WatchDeployEventsRequest,
|
||||
__Marshaller_galaxy_repository_v1_DeployEvent);
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
static readonly grpc::Method<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply> __Method_BrowseChildren = new grpc::Method<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply>(
|
||||
grpc::MethodType.Unary,
|
||||
__ServiceName,
|
||||
"BrowseChildren",
|
||||
__Marshaller_galaxy_repository_v1_BrowseChildrenRequest,
|
||||
__Marshaller_galaxy_repository_v1_BrowseChildrenReply);
|
||||
|
||||
/// <summary>Service descriptor</summary>
|
||||
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
|
||||
{
|
||||
@@ -146,6 +158,21 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy {
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the direct children of a parent object (or the root objects when
|
||||
/// `parent` is unset). Designed for OPC UA-style lazy expand: clients walk
|
||||
/// one level at a time instead of paging the full hierarchy. Filters mirror
|
||||
/// DiscoverHierarchy exactly. Backed by the same shared hierarchy cache.
|
||||
/// </summary>
|
||||
/// <param name="request">The request received from the client.</param>
|
||||
/// <param name="context">The context of the server-side call handler being invoked.</param>
|
||||
/// <returns>The response to send back to the client (wrapped by a task).</returns>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::System.Threading.Tasks.Task<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply> BrowseChildren(global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest request, grpc::ServerCallContext context)
|
||||
{
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Client for GalaxyRepository</summary>
|
||||
@@ -269,6 +296,66 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy {
|
||||
{
|
||||
return CallInvoker.AsyncServerStreamingCall(__Method_WatchDeployEvents, null, options, request);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the direct children of a parent object (or the root objects when
|
||||
/// `parent` is unset). Designed for OPC UA-style lazy expand: clients walk
|
||||
/// one level at a time instead of paging the full hierarchy. Filters mirror
|
||||
/// DiscoverHierarchy exactly. Backed by the same shared hierarchy cache.
|
||||
/// </summary>
|
||||
/// <param name="request">The request to send to the server.</param>
|
||||
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
|
||||
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
|
||||
/// <param name="cancellationToken">An optional token for canceling the call.</param>
|
||||
/// <returns>The response received from the server.</returns>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply BrowseChildren(global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return BrowseChildren(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the direct children of a parent object (or the root objects when
|
||||
/// `parent` is unset). Designed for OPC UA-style lazy expand: clients walk
|
||||
/// one level at a time instead of paging the full hierarchy. Filters mirror
|
||||
/// DiscoverHierarchy exactly. Backed by the same shared hierarchy cache.
|
||||
/// </summary>
|
||||
/// <param name="request">The request to send to the server.</param>
|
||||
/// <param name="options">The options for the call.</param>
|
||||
/// <returns>The response received from the server.</returns>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply BrowseChildren(global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.BlockingUnaryCall(__Method_BrowseChildren, null, options, request);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the direct children of a parent object (or the root objects when
|
||||
/// `parent` is unset). Designed for OPC UA-style lazy expand: clients walk
|
||||
/// one level at a time instead of paging the full hierarchy. Filters mirror
|
||||
/// DiscoverHierarchy exactly. Backed by the same shared hierarchy cache.
|
||||
/// </summary>
|
||||
/// <param name="request">The request to send to the server.</param>
|
||||
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
|
||||
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
|
||||
/// <param name="cancellationToken">An optional token for canceling the call.</param>
|
||||
/// <returns>The call object.</returns>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual grpc::AsyncUnaryCall<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply> BrowseChildrenAsync(global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return BrowseChildrenAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the direct children of a parent object (or the root objects when
|
||||
/// `parent` is unset). Designed for OPC UA-style lazy expand: clients walk
|
||||
/// one level at a time instead of paging the full hierarchy. Filters mirror
|
||||
/// DiscoverHierarchy exactly. Backed by the same shared hierarchy cache.
|
||||
/// </summary>
|
||||
/// <param name="request">The request to send to the server.</param>
|
||||
/// <param name="options">The options for the call.</param>
|
||||
/// <returns>The call object.</returns>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual grpc::AsyncUnaryCall<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply> BrowseChildrenAsync(global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_BrowseChildren, null, options, request);
|
||||
}
|
||||
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
protected override GalaxyRepositoryClient NewInstance(ClientBaseConfiguration configuration)
|
||||
@@ -286,7 +373,8 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy {
|
||||
.AddMethod(__Method_TestConnection, serviceImpl.TestConnection)
|
||||
.AddMethod(__Method_GetLastDeployTime, serviceImpl.GetLastDeployTime)
|
||||
.AddMethod(__Method_DiscoverHierarchy, serviceImpl.DiscoverHierarchy)
|
||||
.AddMethod(__Method_WatchDeployEvents, serviceImpl.WatchDeployEvents).Build();
|
||||
.AddMethod(__Method_WatchDeployEvents, serviceImpl.WatchDeployEvents)
|
||||
.AddMethod(__Method_BrowseChildren, serviceImpl.BrowseChildren).Build();
|
||||
}
|
||||
|
||||
/// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
|
||||
@@ -300,6 +388,7 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy {
|
||||
serviceBinder.AddMethod(__Method_GetLastDeployTime, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.GetLastDeployTimeRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.GetLastDeployTimeReply>(serviceImpl.GetLastDeployTime));
|
||||
serviceBinder.AddMethod(__Method_DiscoverHierarchy, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.DiscoverHierarchyRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.DiscoverHierarchyReply>(serviceImpl.DiscoverHierarchy));
|
||||
serviceBinder.AddMethod(__Method_WatchDeployEvents, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.WatchDeployEventsRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.DeployEvent>(serviceImpl.WatchDeployEvents));
|
||||
serviceBinder.AddMethod(__Method_BrowseChildren, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenRequest, global::ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy.BrowseChildrenReply>(serviceImpl.BrowseChildren));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ service GalaxyRepository {
|
||||
// increasing per server start; gaps indicate the per-subscriber buffer dropped
|
||||
// older events because the client was too slow.
|
||||
rpc WatchDeployEvents(WatchDeployEventsRequest) returns (stream DeployEvent);
|
||||
|
||||
// Returns the direct children of a parent object (or the root objects when
|
||||
// `parent` is unset). Designed for OPC UA-style lazy expand: clients walk
|
||||
// one level at a time instead of paging the full hierarchy. Filters mirror
|
||||
// DiscoverHierarchy exactly. Backed by the same shared hierarchy cache.
|
||||
rpc BrowseChildren(BrowseChildrenRequest) returns (BrowseChildrenReply);
|
||||
}
|
||||
|
||||
message TestConnectionRequest {}
|
||||
@@ -141,3 +147,44 @@ message GalaxyAttribute {
|
||||
bool is_historized = 10;
|
||||
bool is_alarm = 11;
|
||||
}
|
||||
|
||||
message BrowseChildrenRequest {
|
||||
// Parent selector. Empty oneof returns root objects (parent_gobject_id == 0).
|
||||
oneof parent {
|
||||
int32 parent_gobject_id = 1;
|
||||
string parent_tag_name = 2;
|
||||
string parent_contained_path = 3;
|
||||
}
|
||||
|
||||
// Maximum number of direct children to return. Server default 500; cap 5000.
|
||||
int32 page_size = 4;
|
||||
// Opaque token returned by a previous BrowseChildren response. Bound to the
|
||||
// cache sequence, parent selector, and the filter set; a mismatch returns
|
||||
// InvalidArgument.
|
||||
string page_token = 5;
|
||||
|
||||
// --- Filter parity with DiscoverHierarchy. AND-combined. ---
|
||||
repeated int32 category_ids = 6;
|
||||
repeated string template_chain_contains = 7;
|
||||
string tag_name_glob = 8;
|
||||
optional bool include_attributes = 9;
|
||||
bool alarm_bearing_only = 10;
|
||||
bool historized_only = 11;
|
||||
}
|
||||
|
||||
message BrowseChildrenReply {
|
||||
// Direct children matching the filter, sorted areas-first then by
|
||||
// case-insensitive display name (same order as the dashboard tree).
|
||||
repeated GalaxyObject children = 1;
|
||||
// Non-empty when another page of siblings is available.
|
||||
string next_page_token = 2;
|
||||
// Total matching direct children of the parent (post-filter).
|
||||
int32 total_child_count = 3;
|
||||
// Parallel array, indexed with `children`. True when the child has at least
|
||||
// one matching descendant under the same filter set. Lets a UI choose
|
||||
// whether to draw an expand triangle without an extra round trip.
|
||||
repeated bool child_has_children = 4;
|
||||
// Cache sequence this reply was projected from. Clients may pass it back as
|
||||
// part of the page_token contract. Mismatch on the next page -> InvalidArgument.
|
||||
uint64 cache_sequence = 5;
|
||||
}
|
||||
|
||||
@@ -661,6 +661,7 @@ public sealed class ProtobufContractRoundTripTests
|
||||
Assert.Contains(service.Methods, method => method.Name == "GetLastDeployTime");
|
||||
Assert.Contains(service.Methods, method => method.Name == "DiscoverHierarchy");
|
||||
Assert.Contains(service.Methods, method => method.Name == "WatchDeployEvents");
|
||||
Assert.Contains(service.Methods, method => method.Name == "BrowseChildren");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -769,6 +770,114 @@ public sealed class ProtobufContractRoundTripTests
|
||||
Assert.True(parsed.Objects[0].Attributes[0].IsAlarm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a BrowseChildrenRequest round-trips through every
|
||||
/// <c>parent</c> oneof arm with the full filter set populated.
|
||||
/// </summary>
|
||||
/// <param name="parentArm">The oneof arm selector (0=ParentGobjectId, 1=ParentTagName, 2=ParentContainedPath).</param>
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(2)]
|
||||
public void BrowseChildrenRequest_RoundTripsParentOneofAndFilters(int parentArm)
|
||||
{
|
||||
var original = new BrowseChildrenRequest
|
||||
{
|
||||
PageSize = 200,
|
||||
PageToken = "opaque-2",
|
||||
CategoryIds = { 3, 9 },
|
||||
TemplateChainContains = { "Analog", "Pump" },
|
||||
TagNameGlob = "Tank*",
|
||||
IncludeAttributes = true,
|
||||
AlarmBearingOnly = true,
|
||||
HistorizedOnly = false,
|
||||
};
|
||||
switch (parentArm)
|
||||
{
|
||||
case 0:
|
||||
original.ParentGobjectId = 4711;
|
||||
break;
|
||||
case 1:
|
||||
original.ParentTagName = "Tank01";
|
||||
break;
|
||||
default:
|
||||
original.ParentContainedPath = "Area1.Tank01";
|
||||
break;
|
||||
}
|
||||
|
||||
var parsed = BrowseChildrenRequest.Parser.ParseFrom(original.ToByteArray());
|
||||
|
||||
Assert.Equal(original, parsed);
|
||||
Assert.Equal(original.ParentCase, parsed.ParentCase);
|
||||
Assert.NotEqual(BrowseChildrenRequest.ParentOneofCase.None, parsed.ParentCase);
|
||||
Assert.True(parsed.HasIncludeAttributes);
|
||||
Assert.True(parsed.IncludeAttributes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a BrowseChildrenReply round-trips its children list,
|
||||
/// the parallel-indexed <c>child_has_children</c> array, and the
|
||||
/// cache sequence used to bind page tokens.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BrowseChildrenReply_RoundTripsChildrenAndHasChildrenParallelArrays()
|
||||
{
|
||||
var original = new BrowseChildrenReply
|
||||
{
|
||||
NextPageToken = "opaque-3",
|
||||
TotalChildCount = 2,
|
||||
CacheSequence = 42UL,
|
||||
Children =
|
||||
{
|
||||
new GalaxyObject
|
||||
{
|
||||
GobjectId = 4711,
|
||||
TagName = "Tank01",
|
||||
ContainedName = "Tank01",
|
||||
BrowseName = "Tank 01",
|
||||
ParentGobjectId = 12,
|
||||
IsArea = false,
|
||||
CategoryId = 3,
|
||||
HostedByGobjectId = 8,
|
||||
TemplateChain = { "$AnalogDevice", "$Tank" },
|
||||
Attributes =
|
||||
{
|
||||
new GalaxyAttribute
|
||||
{
|
||||
AttributeName = "Level",
|
||||
FullTagReference = "Galaxy!Tank01.Level",
|
||||
MxDataType = 3,
|
||||
DataTypeName = "Float",
|
||||
IsArray = false,
|
||||
ArrayDimension = 0,
|
||||
ArrayDimensionPresent = false,
|
||||
MxAttributeCategory = 1,
|
||||
SecurityClassification = 0,
|
||||
IsHistorized = true,
|
||||
IsAlarm = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
new GalaxyObject
|
||||
{
|
||||
GobjectId = 12,
|
||||
TagName = "Area1",
|
||||
IsArea = true,
|
||||
},
|
||||
},
|
||||
ChildHasChildren = { true, false },
|
||||
};
|
||||
|
||||
var parsed = BrowseChildrenReply.Parser.ParseFrom(original.ToByteArray());
|
||||
|
||||
Assert.Equal(original, parsed);
|
||||
Assert.Equal(2, parsed.Children.Count);
|
||||
Assert.Equal(2, parsed.ChildHasChildren.Count);
|
||||
Assert.True(parsed.ChildHasChildren[0]);
|
||||
Assert.False(parsed.ChildHasChildren[1]);
|
||||
Assert.Equal(42UL, parsed.CacheSequence);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a DeployEvent round-trips with its timestamp and counters.</summary>
|
||||
[Fact]
|
||||
public void DeployEvent_RoundTripsTimestampAndCounters()
|
||||
|
||||
Reference in New Issue
Block a user