Files
mxaccessgw/clients/go
Joseph Doherty 397d3c5c4f rename: apply ZB.MOM.WW prefix to all client SDKs + fix pre-existing alarm-RPC breaks
Rename across every client surface using each language's idiomatic convention:

  * .NET   clients/dotnet/MxGateway.Client[.Cli|.Tests]/
             -> clients/dotnet/ZB.MOM.WW.MxGateway.Client[.Cli|.Tests]/
             namespaces -> ZB.MOM.WW.MxGateway.Client[.Cli|.Tests]
             contracts ProjectReference repointed to ZB.MOM.WW.MxGateway.Contracts
             sln migrated to slnx (dotnet sln migrate)
  * Python src/mxgateway -> src/zb_mom_ww_mxgateway
             src/mxgateway_cli -> src/zb_mom_ww_mxgateway_cli
             distribution: mxaccess-gateway-client -> zb-mom-ww-mxaccess-gateway-client
  * Rust   crate: mxgateway-client -> zb-mom-ww-mxgateway-client
             build.rs proto path repointed
  * Java   subprojects: mxgateway-{client,cli} -> zb-mom-ww-mxgateway-{client,cli}
             packages com.dohertylan.mxgateway -> com.zb.mom.ww.mxgateway
             group   com.dohertylan.mxgateway -> com.zb.mom.ww.mxgateway
             rootProject mxaccessgw-java -> zb-mom-ww-mxaccessgw-java
  * Go     generate-proto.ps1 proto path repointed; module path and
             package mxgateway kept (Go convention).
  * proto-inputs.json: generatedOutputs.python updated to new package path.
  * scripts/run-client-e2e-tests.ps1: Java CLI install path + gradle task
             updated to zb-mom-ww-mxgateway-cli.

CLI binary names (mxgw, mxgw-py, mxgw-go, mxgateway-cli) and wire-level
identifiers (MXGATEWAY_* env vars, the mxgw_<id>_<secret> API key
prefix, protobuf package names like mxaccess_gateway.v1, all MXAccess
references) intentionally NOT renamed.

Fix pre-existing alarms-over-gateway breaks unblocked by the rename:

  * mxaccess_gateway.proto: add missing public message QueryActiveAlarmsRequest
    {session_id, client_correlation_id, alarm_filter_prefix} and missing
    rpc QueryActiveAlarms(QueryActiveAlarmsRequest) returns
    (stream ActiveAlarmSnapshot). All four typed clients referenced
    these but they were absent from the proto.
  * MxAccessGatewayService.QueryActiveAlarms: implement the new RPC on
    the server, streaming from IGatewayAlarmService.CurrentAlarms with
    optional alarm_filter_prefix filter.
  * clients/dotnet/.../DiscoverHierarchyOptions.cs: add the hand-written
    .NET POCO that wraps DiscoverHierarchyRequest (referenced by
    GalaxyRepositoryClient.DiscoverHierarchyAsync but never authored).
  * Drop retired session_id field references from
    AcknowledgeAlarmRequest/AcknowledgeAlarmReply test fixtures across
    .NET, Rust, Go, and Python clients.
  * Rust integration test: add the missing stream_alarms impl on the
    fake MxAccessGateway server (the trait gained the method, fake
    didn't).
  * Rust CLI test: bump expected gatewayProtocolVersion 2 -> 3.

Regenerated artifacts updated in this commit:
  * src/ZB.MOM.WW.MxGateway.Contracts/Generated/{MxaccessGateway,MxaccessGatewayGrpc}.cs
  * clients/python/src/zb_mom_ww_mxgateway/generated/*_pb2{,_grpc}.py
  * clients/go/internal/generated/*.pb.go
(C# regenerated by Grpc.Tools on contracts build; Python and Go via
their generate-proto.ps1 scripts; Rust regenerates from .proto via
tonic-build at compile time so no checked-in artefact.)

Verification: 472 server tests, 275 worker tests (9 dev-rig skipped),
18 integration tests (live MxAccess + LDAP + Galaxy), 57 .NET client
tests, 32 Rust workspace tests, 39 Python tests, all Go packages, and
gradle build for Java all pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 19:09:34 -04:00
..
2026-04-26 19:27:27 -04:00
2026-04-26 19:27:27 -04:00

Go Client

The Go client module contains the generated MXAccess Gateway protobuf bindings, a small handwritten mxgateway package, and the mxgw-go test CLI scaffold. The module uses the shared proto inputs documented in ../../docs/ClientProtoGeneration.md so gateway and client contracts stay in sync.

Layout

clients/go/
  go.mod
  generate-proto.ps1
  internal/generated/
  mxgateway/
  cmd/mxgw-go/

internal/generated contains code produced by protoc, protoc-gen-go, and protoc-gen-go-grpc. Do not edit generated files by hand.

Regenerating Protobuf Bindings

Run generation after the shared .proto files or the Go output path changes:

./generate-proto.ps1

The script uses the tool paths recorded in ../../docs/ToolchainLinks.md.

Build And Test

Run the Go module checks from clients/go:

go test ./...
go build ./...
go vet ./...

The tests parse the shared JSON fixtures, exercise value and status conversion, use bufconn for fake gateway auth and streaming behavior, and cover CLI JSON redaction.

Packaging

Build a local CLI executable from clients/go:

New-Item -ItemType Directory -Force ../../artifacts/clients/go | Out-Null
go build -o ../../artifacts/clients/go/mxgw-go.exe ./cmd/mxgw-go

Install the CLI into the active GOBIN or GOPATH/bin:

go install ./cmd/mxgw-go

Other Go modules can consume the library package with the module path gitea.dohertylan.com/dohertj2/mxaccessgw/clients/go/mxgateway.

Client API

Use mxgateway.Dial with mxgateway.Options to configure plaintext or TLS transport, API-key metadata, dial timeout, and per-call timeout:

client, err := mxgateway.Dial(ctx, mxgateway.Options{
    Endpoint:  "localhost:5000",
    APIKey:    os.Getenv("MXGATEWAY_API_KEY"),
    Plaintext: true,
})

Client.OpenSession returns a Session with helpers for Register, AddItem, AddItem2, Advise, Write, Events, and Close. Prefer SubscribeEvents or SubscribeEventsAfter for long-running streams because the returned subscription owns cancellation and exposes Close for deterministic goroutine cleanup. Raw protobuf messages remain available through the mxgateway package aliases and the Raw helper methods. Typed errors support errors.As for GatewayError, CommandError, and MxAccessError; command errors preserve the raw reply.

Galaxy Repository browse

The GalaxyRepository service (proto package galaxy_repository.v1) is a read-only metadata-only browse over the AVEVA System Platform Galaxy Repository. It uses the same API-key authentication as the MXAccess Gateway and requires the metadata:read scope. Use mxgateway.DialGalaxy to obtain a *GalaxyClient that mirrors the connection-management conventions of Client:

galaxy, err := mxgateway.DialGalaxy(ctx, mxgateway.Options{
    Endpoint:  "localhost:5000",
    APIKey:    os.Getenv("MXGATEWAY_API_KEY"),
    Plaintext: true,
})
if err != nil {
    return err
}
defer galaxy.Close()

ok, err := galaxy.TestConnection(ctx)
deployTime, present, err := galaxy.GetLastDeployTime(ctx)
objects, err := galaxy.DiscoverHierarchy(ctx)

GetLastDeployTime returns (time.Time{}, false, nil) when the server reports present=false (no deploy recorded). DiscoverHierarchy returns the generated *GalaxyObject slice with each object's dynamic attributes populated for direct contract access.

Watching deploy events

WatchDeployEvents opens a server-streaming subscription. The server emits a bootstrap event with the current Galaxy state immediately on subscribe, then one DeployEvent per new deploy. Sequence is monotonic per server start; gaps signal dropped events. Pass a non-nil lastSeenDeployTime to suppress the bootstrap event when resuming from a known checkpoint:

streamCtx, cancel := context.WithCancel(ctx)
defer cancel()

events, errs, err := galaxy.WatchDeployEvents(streamCtx, nil)
if err != nil {
    return err
}

for {
    select {
    case ev, ok := <-events:
        if !ok {
            return nil // stream completed (server EOF or ctx cancelled)
        }
        log.Printf("seq=%d objects=%d attrs=%d",
            ev.GetSequence(), ev.GetObjectCount(), ev.GetAttributeCount())
    case streamErr := <-errs:
        if streamErr != nil {
            return streamErr // *GatewayError
        }
    case <-ctx.Done():
        return ctx.Err()
    }
}

Cancel the supplied context to tear down the stream cleanly. Both channels close after EOF, cancellation, or a terminal error; surfaced errors are wrapped in *GatewayError.

The CLI exposes the same RPC via galaxy-watch:

go run ./cmd/mxgw-go galaxy-watch -plaintext
go run ./cmd/mxgw-go galaxy-watch -plaintext -json
go run ./cmd/mxgw-go galaxy-watch -plaintext -last-seen-deploy-time 2026-04-28T10:00:00Z
go run ./cmd/mxgw-go galaxy-watch -plaintext -limit 5

The command runs until Ctrl+C (or the optional -limit is reached) and prints one line per event in text mode or one JSON object per event with -json.

CLI

The mxgw-go CLI emits JSON with redacted API keys for commands that connect to the gateway:

go run ./cmd/mxgw-go version -json
go run ./cmd/mxgw-go open-session -endpoint localhost:5000 -plaintext -json
go run ./cmd/mxgw-go register -session-id <id> -client-name mxgw-go -plaintext -json
go run ./cmd/mxgw-go add-item -session-id <id> -server-handle 1 -item Area001.Tag.Value -plaintext -json
go run ./cmd/mxgw-go advise -session-id <id> -server-handle 1 -item-handle 1 -plaintext -json
go run ./cmd/mxgw-go write -session-id <id> -server-handle 1 -item-handle 1 -type int32 -value 123 -plaintext -json
go run ./cmd/mxgw-go stream-events -session-id <id> -plaintext -json
go run ./cmd/mxgw-go smoke -item Area001.Tag.Value -plaintext -json
go run ./cmd/mxgw-go galaxy-test-connection -plaintext -json
go run ./cmd/mxgw-go galaxy-last-deploy -plaintext -json
go run ./cmd/mxgw-go galaxy-discover -plaintext -json
go run ./cmd/mxgw-go galaxy-watch -plaintext -json

Use -api-key-env MXGATEWAY_API_KEY or -api-key <key> when authentication is enabled. CLI output redacts the key value and never writes the raw secret.

Use TLS options for a secured gateway:

go run ./cmd/mxgw-go smoke -endpoint mxgateway.example.local:5001 -ca-cert C:\certs\mxgateway-ca.pem -server-name-override mxgateway.example.local -api-key-env MXGATEWAY_API_KEY -item Area001.Tag.Value -json

Integration Checks

Run live checks only when a gateway and MXAccess-backed worker are available:

$env:MXGATEWAY_INTEGRATION = '1'
$env:MXGATEWAY_ENDPOINT = 'localhost:5000'
$env:MXGATEWAY_API_KEY = '<gateway-api-key>'
$env:MXGATEWAY_TEST_ITEM = 'Area001.Tag.Value'
go run ./cmd/mxgw-go smoke -endpoint $env:MXGATEWAY_ENDPOINT -plaintext -api-key-env MXGATEWAY_API_KEY -item $env:MXGATEWAY_TEST_ITEM -json