using Grpc.Core; using ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy; using ZB.MOM.WW.MxGateway.Server.Galaxy; namespace ZB.MOM.WW.MxGateway.Server.Dashboard; /// /// Default . Delegates to /// via the shared /// ; no SQL hop, no gRPC self-call. Translates /// the projector's on unknown parent into a friendly /// so the Blazor circuit does not see an /// unhandled exception. /// public sealed class DashboardBrowseService(IGalaxyHierarchyCache cache) : IDashboardBrowseService { /// public ulong CurrentCacheSequence => (ulong)cache.Current.Sequence; /// public BrowseLevelResult GetRoots(BrowseFilterArgs filter) => ProjectLevel(parentId: null, filter); /// public BrowseLevelResult GetChildren(int parentGobjectId, BrowseFilterArgs filter) => ProjectLevel(parentId: parentGobjectId, filter); private BrowseLevelResult ProjectLevel(int? parentId, BrowseFilterArgs filter) { ArgumentNullException.ThrowIfNull(filter); GalaxyHierarchyCacheEntry entry = cache.Current; if (!entry.HasData) { return new BrowseLevelResult( Array.Empty(), 0, (ulong)entry.Sequence, Error: "Galaxy hierarchy is not loaded yet."); } BrowseChildrenRequest request = new() { TagNameGlob = filter.TagNameGlob ?? string.Empty, AlarmBearingOnly = filter.AlarmBearingOnly, HistorizedOnly = filter.HistorizedOnly, }; if (parentId is int pid) { request.ParentGobjectId = pid; } try { GalaxyBrowseChildrenResult result = GalaxyBrowseProjector.ProjectChildren( entry, request, browseSubtreeGlobs: null, offset: 0, pageSize: int.MaxValue); List nodes = new(result.Children.Count); for (int i = 0; i < result.Children.Count; i++) { nodes.Add(new DashboardBrowseNode { Object = result.Children[i], HasChildrenHint = result.ChildHasChildren[i], }); } return new BrowseLevelResult(nodes, result.TotalChildCount, (ulong)entry.Sequence); } catch (RpcException ex) when (ex.StatusCode == StatusCode.NotFound) { return new BrowseLevelResult( Array.Empty(), 0, (ulong)entry.Sequence, Error: ex.Status.Detail); } } }