R4.3: gRPC store-forward status probe + re-scope
Add HistorianGrpcStoreForwardStatusProbe and the `grpc-sf-status-probe` CLI command. The idle-baseline run against the live 2023 R2 server resolves the plan's §9.3 handle question: the direct StorageService SF pull RPCs (GetSFParameter / GetRemainingSnapshotsSize) require the OpenStorageConnection console handle and are D2-gated (err 132, identical under read-only and write-enabled sessions), while StatusService.GetHistorianConsoleStatus IS reachable on the session string handle (=3 at idle). Records the gRPC re-scope and the idle-baseline findings in docs/plans/store-forward-cache-reverse-engineering.md §9. The probe writes nothing and releases any console session immediately. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
@@ -78,6 +78,7 @@ try
|
||||
"grpc-revision-probe" => ProbeGrpcRevision(args),
|
||||
"grpc-nonstream-decode" => ProbeGrpcNonStreamedDecode(args),
|
||||
"grpc-open-storage-connection" => ProbeGrpcOpenStorageConnection(args),
|
||||
"grpc-sf-status-probe" => ProbeGrpcStoreForwardStatus(args),
|
||||
_ => UnknownCommand(args[0])
|
||||
};
|
||||
}
|
||||
@@ -3386,6 +3387,48 @@ static int ProbeGrpcOpenStorageConnection(string[] args)
|
||||
return result.OpenStorageSucceeded ? 0 : 2;
|
||||
}
|
||||
|
||||
static int ProbeGrpcStoreForwardStatus(string[] args)
|
||||
{
|
||||
// Usage: grpc-sf-status-probe <host> [port] [--tls] [--dnsid <name>]
|
||||
// R4.3 idle-baseline discovery (see docs/plans/store-forward-cache-reverse-engineering.md §9).
|
||||
// Reads store-forward state via StorageService PULL RPCs (GetRemainingSnapshotsSize + sweep of
|
||||
// GetSFParameter). Tries the cheap session ClientHandle first; falls back to an
|
||||
// OpenStorageConnection console handle only if that fails, to disambiguate §9.3. Writes NOTHING.
|
||||
// Reads HISTORIAN_USER / HISTORIAN_PASSWORD for explicit creds; else IntegratedSecurity.
|
||||
string host = args.Length > 1 ? args[1] : "localhost";
|
||||
int port = args.Length > 2 && int.TryParse(args[2], out int parsedPort)
|
||||
? parsedPort
|
||||
: HistorianClientOptions.DefaultGrpcPort;
|
||||
bool tls = HasOption(args, "--tls");
|
||||
string? dnsId = GetOption(args, "--dnsid");
|
||||
|
||||
string? user = Environment.GetEnvironmentVariable("HISTORIAN_USER");
|
||||
string? password = Environment.GetEnvironmentVariable("HISTORIAN_PASSWORD");
|
||||
bool explicitCreds = !string.IsNullOrEmpty(user);
|
||||
|
||||
var options = new HistorianClientOptions
|
||||
{
|
||||
Host = host,
|
||||
Port = port,
|
||||
Transport = HistorianTransport.RemoteGrpc,
|
||||
GrpcUseTls = tls,
|
||||
AllowUntrustedServerCertificate = tls,
|
||||
ServerDnsIdentity = dnsId,
|
||||
IntegratedSecurity = !explicitCreds,
|
||||
UserName = user ?? string.Empty,
|
||||
Password = password ?? string.Empty,
|
||||
};
|
||||
|
||||
bool writeSession = HasOption(args, "--write-session");
|
||||
var probe = new HistorianGrpcStoreForwardStatusProbe(options, writeSession);
|
||||
HistorianGrpcStoreForwardStatusProbeResult result = probe.ProbeAsync(CancellationToken.None).GetAwaiter().GetResult();
|
||||
Console.WriteLine(JsonSerializer.Serialize(result, CreateJsonOptions()));
|
||||
|
||||
bool anySucceeded = (result.SessionHandleAttempt?.AnySucceeded ?? false)
|
||||
|| (result.ConsoleHandleAttempt?.AnySucceeded ?? false);
|
||||
return anySucceeded ? 0 : 2;
|
||||
}
|
||||
|
||||
static int ProbeGrpcRevision(string[] args)
|
||||
{
|
||||
// Usage: grpc-revision-probe <host> [port] [--tls] [--dnsid <name>] [--insecure-cert]
|
||||
|
||||
Reference in New Issue
Block a user