Resolve Client.Java-006..012 code-review findings
Client.Java-006: close() on both clients only called shutdown(). It now awaits termination up to the connect timeout and shutdownNow()s on timeout. Client.Java-007: added MxGatewayLowFindingsTests covering the alarm surface, async streaming, MxEventStream overflow, and TLS channel construction. A latent bug surfaced: a missing CA file throws IllegalArgumentException, not SSLException — the channel-builder catch was broadened accordingly. Client.Java-008: async thenApply sites now route stray RuntimeExceptions through MxGatewayErrors.fromGrpc via a normalising validator. Client.Java-009: extracted ~80 duplicated lines (createChannel, withDeadline, toCompletable, ...) into a shared MxGatewayChannels; both clients delegate. Client.Java-010 (re-triaged): the README's metadata:read scope was correct; the acknowledgeAlarm Javadoc's invoke:alarm-ack was wrong — corrected to the admin scope. Client.Java-011: documented the intentional fail-fast event-stream backpressure in Javadoc and the README. Client.Java-012: replaced CommonOptions.resolved()'s mutate-and-return-this with side-effect-free resolvedApiKey()/resolvedTimeout() accessors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+38
-11
@@ -661,33 +661,60 @@ public final class MxGatewayCli implements Callable<Integer> {
|
||||
@Option(names = "--timeout", defaultValue = "30s", description = "Per-call timeout.")
|
||||
String timeout;
|
||||
|
||||
private String resolvedApiKey = "";
|
||||
private Duration resolvedTimeout = Duration.ofSeconds(30);
|
||||
|
||||
/**
|
||||
* Returns this options object unchanged.
|
||||
*
|
||||
* <p>Retained as a no-op for call sites that read more naturally as
|
||||
* {@code common.resolved()}. Resolution of the API key and timeout is
|
||||
* computed lazily on demand by {@link #resolvedApiKey()} and
|
||||
* {@link #resolvedTimeout()}, so {@link #toClientOptions()} and
|
||||
* {@link #redactedJsonMap()} produce correct output regardless of
|
||||
* whether this method was ever called.
|
||||
*
|
||||
* @return this options object
|
||||
*/
|
||||
CommonOptions resolved() {
|
||||
resolvedApiKey = apiKey == null || apiKey.isBlank() ? System.getenv(apiKeyEnv) : apiKey;
|
||||
if (resolvedApiKey == null) {
|
||||
resolvedApiKey = "";
|
||||
}
|
||||
resolvedTimeout = parseDuration(timeout);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the effective API key: the explicit {@code --api-key} value
|
||||
* when non-blank, otherwise the value of the {@code --api-key-env}
|
||||
* environment variable, otherwise an empty string. Computed on each
|
||||
* call so there is no stale cached state.
|
||||
*
|
||||
* @return the resolved API key, never {@code null}
|
||||
*/
|
||||
String resolvedApiKey() {
|
||||
String resolved = apiKey == null || apiKey.isBlank() ? System.getenv(apiKeyEnv) : apiKey;
|
||||
return resolved == null ? "" : resolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the effective per-call timeout from the {@code --timeout}
|
||||
* option. Computed on each call so there is no stale cached state.
|
||||
*
|
||||
* @return the resolved call timeout
|
||||
*/
|
||||
Duration resolvedTimeout() {
|
||||
return parseDuration(timeout);
|
||||
}
|
||||
|
||||
MxGatewayClientOptions toClientOptions() {
|
||||
return MxGatewayClientOptions.builder()
|
||||
.endpoint(endpoint)
|
||||
.apiKey(resolvedApiKey)
|
||||
.apiKey(resolvedApiKey())
|
||||
.plaintext(plaintext)
|
||||
.caCertificatePath(caFile)
|
||||
.serverNameOverride(serverNameOverride)
|
||||
.callTimeout(resolvedTimeout)
|
||||
.callTimeout(resolvedTimeout())
|
||||
.build();
|
||||
}
|
||||
|
||||
Map<String, Object> redactedJsonMap() {
|
||||
Map<String, Object> values = new LinkedHashMap<>();
|
||||
values.put("endpoint", endpoint);
|
||||
values.put("apiKey", MxGatewaySecrets.redactApiKey(resolvedApiKey));
|
||||
values.put("apiKey", MxGatewaySecrets.redactApiKey(resolvedApiKey()));
|
||||
values.put("apiKeyEnv", apiKeyEnv);
|
||||
values.put("plaintext", plaintext);
|
||||
values.put("caFile", caFile == null ? "" : caFile.toString());
|
||||
|
||||
Reference in New Issue
Block a user