From a15555403831db88a2b8c20ce3f748bb958ce3da Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 28 May 2026 15:32:48 -0400 Subject: [PATCH] grpc: reuse GalaxyBrowseProjector.ResolveParentId from handler --- .../Galaxy/GalaxyBrowseProjector.cs | 11 ++++++- .../Grpc/GalaxyRepositoryGrpcService.cs | 33 +++---------------- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs index d6a5135..1768fb3 100644 --- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs +++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs @@ -62,7 +62,16 @@ public static class GalaxyBrowseProjector return new GalaxyBrowseChildrenResult(page, hasChildren, filtered.Children.Count, filterSignature); } - private static int ResolveParentId(GalaxyHierarchyCacheEntry entry, BrowseChildrenRequest request) + /// + /// Resolves the request's parent oneof to a gobject id, throwing + /// with when the + /// parent does not exist. Public so the gRPC handler can compute the same + /// parent id (needed for the page-token signature) without reimplementing the + /// resolution rules. + /// + /// The Galaxy hierarchy cache entry to query. + /// The browse-children request. + public static int ResolveParentId(GalaxyHierarchyCacheEntry entry, BrowseChildrenRequest request) { switch (request.ParentCase) { diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyRepositoryGrpcService.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyRepositoryGrpcService.cs index 8bce0a5..0113b81 100644 --- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyRepositoryGrpcService.cs +++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyRepositoryGrpcService.cs @@ -128,8 +128,11 @@ public sealed class GalaxyRepositoryGrpcService( IReadOnlyList browseSubtrees = ResolveBrowseSubtrees(); // Resolve the parent id once so the page-token signature can include it - // and the projector sees the same resolved id when memoizing. - int parentId = ResolveParentIdForToken(entry, request); + // and the projector sees the same resolved id when memoizing. The projector + // re-resolves internally; with the by-name/by-path indexes on + // GalaxyHierarchyIndex that second call is O(1), so the redundancy is cheap + // and keeps the projector self-contained. + int parentId = GalaxyDb.GalaxyBrowseProjector.ResolveParentId(entry, request); string filterSignature = GalaxyDb.GalaxyBrowseProjector.ComputeFilterSignature( request, browseSubtrees, parentId); PageToken pageToken = ParsePageToken(request.PageToken, entry.Sequence, filterSignature); @@ -283,32 +286,6 @@ public sealed class GalaxyRepositoryGrpcService( return Math.Min(pageSize, MaxDiscoverPageSize); } - // Lightweight parent resolver used only for signature computation. Re-throws - // NotFound consistently with the projector so the error surface matches. - private static int ResolveParentIdForToken( - GalaxyDb.GalaxyHierarchyCacheEntry entry, - BrowseChildrenRequest request) - { - return request.ParentCase switch - { - BrowseChildrenRequest.ParentOneofCase.None => 0, - BrowseChildrenRequest.ParentOneofCase.ParentGobjectId => - request.ParentGobjectId == 0 ? 0 - : entry.Index.ObjectViewsById.ContainsKey(request.ParentGobjectId) - ? request.ParentGobjectId - : throw new RpcException(new Status(StatusCode.NotFound, "BrowseChildren parent was not found.")), - BrowseChildrenRequest.ParentOneofCase.ParentTagName => - entry.Index.ObjectViews.FirstOrDefault( - v => string.Equals(v.Object.TagName, request.ParentTagName, StringComparison.OrdinalIgnoreCase))?.Object.GobjectId - ?? throw new RpcException(new Status(StatusCode.NotFound, "BrowseChildren parent was not found.")), - BrowseChildrenRequest.ParentOneofCase.ParentContainedPath => - entry.Index.ObjectViews.FirstOrDefault( - v => string.Equals(v.ContainedPath, request.ParentContainedPath, StringComparison.OrdinalIgnoreCase))?.Object.GobjectId - ?? throw new RpcException(new Status(StatusCode.NotFound, "BrowseChildren parent was not found.")), - _ => 0, - }; - } - private IReadOnlyList ResolveBrowseSubtrees() { ApiKeyConstraints constraints = identityAccessor.Current?.EffectiveConstraints ?? ApiKeyConstraints.Empty;