docs(xml): fill missing XML doc comments + strip task-tracking refs across src (fixdocs)
Add missing <summary>/<param>/<returns>/<typeparam> tags and switch interface implementations to <inheritdoc/> across 106 files; strip project bookkeeping identifiers (Task NN, #05-TNN, PLAN-04, StoreAndForward-0NN) from shipped code comments while preserving the descriptive rationale. Comment-only: zero code-logic lines changed; solution builds 0/0. Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
@@ -3,7 +3,14 @@ namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier;
|
||||
/// <summary>Outcome of parsing the command line: success carries the payload, failure carries a human reason.</summary>
|
||||
internal sealed record ParseResult(bool Ok, RecipeDownload? Payload, string? Error)
|
||||
{
|
||||
/// <summary>Builds a successful parse result carrying the parsed payload.</summary>
|
||||
/// <param name="payload">The successfully parsed recipe download payload.</param>
|
||||
/// <returns>A <see cref="ParseResult"/> with <see cref="Ok"/> set to <c>true</c>.</returns>
|
||||
public static ParseResult Success(RecipeDownload payload) => new(true, payload, null);
|
||||
|
||||
/// <summary>Builds a failed parse result carrying a human-readable reason.</summary>
|
||||
/// <param name="error">The human-readable failure reason.</param>
|
||||
/// <returns>A <see cref="ParseResult"/> with <see cref="Ok"/> set to <c>false</c>.</returns>
|
||||
public static ParseResult Fail(string error) => new(false, null, error);
|
||||
}
|
||||
|
||||
@@ -13,6 +20,9 @@ internal sealed record ParseResult(bool Ok, RecipeDownload? Payload, string? Err
|
||||
/// </summary>
|
||||
internal static class ArgParser
|
||||
{
|
||||
/// <summary>Parses the legacy WWNotifier command-line flags into a <see cref="RecipeDownload"/> payload.</summary>
|
||||
/// <param name="args">The raw command-line arguments.</param>
|
||||
/// <returns>A successful <see cref="ParseResult"/> with the parsed payload, or a failed one with the reason.</returns>
|
||||
public static ParseResult Parse(string[] args)
|
||||
{
|
||||
var payload = new RecipeDownload();
|
||||
|
||||
@@ -8,10 +8,13 @@ internal static class ConfigLoader
|
||||
private const string ApiKeyEnvVar = "SCADABRIDGE_API_KEY";
|
||||
|
||||
/// <summary>Deserialize the <c>appsettings.json</c> text via the source-gen context.</summary>
|
||||
/// <param name="jsonText">The raw JSON text of <c>appsettings.json</c>.</param>
|
||||
/// <returns>The deserialized <see cref="NotifierConfig"/>, or a default instance if deserialization yields <c>null</c>.</returns>
|
||||
public static NotifierConfig Load(string jsonText) =>
|
||||
JsonSerializer.Deserialize(jsonText, NotifierJsonContext.Default.NotifierConfig) ?? new NotifierConfig();
|
||||
|
||||
/// <summary>Read and parse the <c>appsettings.json</c> sitting next to the executable.</summary>
|
||||
/// <returns>The deserialized <see cref="NotifierConfig"/>.</returns>
|
||||
public static NotifierConfig LoadFromDefaultFile()
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "appsettings.json");
|
||||
@@ -19,6 +22,8 @@ internal static class ConfigLoader
|
||||
}
|
||||
|
||||
/// <summary>Split a comma-separated base-URL list into trimmed, non-empty entries.</summary>
|
||||
/// <param name="baseUrls">The comma-separated base-URL list, or <c>null</c>/empty.</param>
|
||||
/// <returns>The trimmed, non-empty base URLs; an empty array if none.</returns>
|
||||
public static string[] SplitBaseUrls(string? baseUrls)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(baseUrls))
|
||||
@@ -30,6 +35,8 @@ internal static class ConfigLoader
|
||||
}
|
||||
|
||||
/// <summary>Resolve the API key from <c>SCADABRIDGE_API_KEY</c>; null/whitespace → null. Env accessor is injected for testability.</summary>
|
||||
/// <param name="envGet">Accessor used to read an environment variable by name.</param>
|
||||
/// <returns>The resolved API key, or <c>null</c> if unset/whitespace.</returns>
|
||||
public static string? ResolveApiKey(Func<string, string?> envGet)
|
||||
{
|
||||
var key = envGet(ApiKeyEnvVar);
|
||||
|
||||
@@ -10,6 +10,8 @@ internal sealed class DiagLog(string? logPath)
|
||||
{
|
||||
private readonly string? _logPath = string.IsNullOrWhiteSpace(logPath) ? null : logPath;
|
||||
|
||||
/// <summary>Writes a UTC-timestamped diagnostic line to stderr and, if configured, the log file.</summary>
|
||||
/// <param name="message">The message text to log.</param>
|
||||
public void Write(string message)
|
||||
{
|
||||
var line = string.Create(CultureInfo.InvariantCulture, $"{DateTime.UtcNow:yyyy-MM-ddTHH:mm:ss.fffZ} {message}");
|
||||
|
||||
@@ -12,6 +12,7 @@ internal sealed class HttpRecipeSender(HttpClient http, string apiKey) : IRecipe
|
||||
{
|
||||
private const string MethodPath = "/api/DelmiaRecipeDownload";
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<AttemptOutcome> SendAsync(string baseUrl, RecipeDownload payload, CancellationToken ct)
|
||||
{
|
||||
var url = baseUrl.TrimEnd('/') + MethodPath;
|
||||
|
||||
@@ -17,5 +17,10 @@ internal sealed record AttemptOutcome(AttemptKind Kind, int StatusCode, RecipeDo
|
||||
/// <summary>Seam over a single recipe-download POST attempt, so the failover loop is testable without real HTTP.</summary>
|
||||
internal interface IRecipeSender
|
||||
{
|
||||
/// <summary>Sends the recipe download payload to a single base URL as one POST attempt.</summary>
|
||||
/// <param name="baseUrl">The base URL to POST the recipe download to.</param>
|
||||
/// <param name="payload">The recipe download payload to send.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>The outcome of the attempt: connected (with status/body) or connect-failed (with error detail).</returns>
|
||||
Task<AttemptOutcome> SendAsync(string baseUrl, RecipeDownload payload, CancellationToken ct);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,16 @@ internal sealed record NotifyResult(bool Ok, string Reason);
|
||||
/// </summary>
|
||||
internal static class Notifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs the connect-failure-only failover loop across <paramref name="baseUrls"/>,
|
||||
/// sending <paramref name="payload"/> via <paramref name="sender"/> until a node
|
||||
/// responds (connects) or every URL fails to connect.
|
||||
/// </summary>
|
||||
/// <param name="baseUrls">Base URLs to try in order.</param>
|
||||
/// <param name="payload">The recipe-download payload to send.</param>
|
||||
/// <param name="sender">The sender used to POST the payload to each base URL.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>A task that resolves to the final notify outcome.</returns>
|
||||
public static async Task<NotifyResult> RunAsync(
|
||||
string[] baseUrls, RecipeDownload payload, IRecipeSender sender, CancellationToken ct)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier;
|
||||
/// <summary>Root of <c>appsettings.json</c>; mirrors the <c>ScadaBridge</c> section only.</summary>
|
||||
internal sealed class NotifierConfig
|
||||
{
|
||||
/// <summary>The <c>ScadaBridge</c> configuration section (base URLs, timeout, log path).</summary>
|
||||
public ScadaBridgeSection ScadaBridge { get; set; } = new();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@ namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>Entry point: loads config, sends the recipe-download notification with failover across the configured base URLs, and reports the legacy YES/NO stdout contract.</summary>
|
||||
/// <param name="args">Command-line arguments parsed into the recipe download payload.</param>
|
||||
/// <returns>A task that resolves to the process exit code.</returns>
|
||||
public static async Task<int> Main(string[] args)
|
||||
{
|
||||
var stdout = Console.Out;
|
||||
@@ -61,6 +64,7 @@ internal static class Program
|
||||
/// <summary>Decorates a sender to emit a per-attempt diagnostic line; keeps stdout reserved for the YES/NO contract.</summary>
|
||||
private sealed class LoggingRecipeSender(IRecipeSender inner, DiagLog log) : IRecipeSender
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<AttemptOutcome> SendAsync(string baseUrl, RecipeDownload payload, CancellationToken ct)
|
||||
{
|
||||
var outcome = await inner.SendAsync(baseUrl, payload, ct);
|
||||
|
||||
@@ -2,10 +2,21 @@ namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier;
|
||||
|
||||
internal sealed class RecipeDownload
|
||||
{
|
||||
/// <summary>Identifier of the machine the recipe is being downloaded to.</summary>
|
||||
public string? MachineCode { get; set; }
|
||||
|
||||
/// <summary>Filesystem/network path the recipe should be downloaded into.</summary>
|
||||
public string? DownloadPath { get; set; }
|
||||
|
||||
/// <summary>DELMIA work order number the recipe download is associated with.</summary>
|
||||
public string? WorkOrderNumber { get; set; }
|
||||
|
||||
/// <summary>Part number the recipe applies to.</summary>
|
||||
public string? PartNumber { get; set; }
|
||||
|
||||
/// <summary>Job step number within the work order the recipe download corresponds to.</summary>
|
||||
public string? JobStepNumber { get; set; }
|
||||
|
||||
/// <summary>Username of the operator that triggered the recipe download.</summary>
|
||||
public string? Username { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier;
|
||||
|
||||
/// <summary>Deserialized response body from the Inbound API recipe-download call.</summary>
|
||||
internal sealed class RecipeDownloadResult
|
||||
{
|
||||
/// <summary>Whether the recipe download succeeded.</summary>
|
||||
public bool Result { get; set; }
|
||||
|
||||
/// <summary>Human-readable status/error text accompanying <see cref="Result"/>.</summary>
|
||||
public string? ResultText { get; set; }
|
||||
}
|
||||
|
||||
@@ -7,6 +7,11 @@ namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier;
|
||||
/// </summary>
|
||||
internal static class Reporter
|
||||
{
|
||||
/// <summary>Writes the legacy WWNotifier stdout contract for the given outcome.</summary>
|
||||
/// <param name="ok">Whether the operation succeeded.</param>
|
||||
/// <param name="reason">The failure reason to write when <paramref name="ok"/> is <c>false</c>; ignored on success.</param>
|
||||
/// <param name="stdout">The writer to which the contract output is written.</param>
|
||||
/// <returns>0 on success; -1 on failure.</returns>
|
||||
public static int Report(bool ok, string reason, TextWriter stdout)
|
||||
{
|
||||
if (ok)
|
||||
|
||||
Reference in New Issue
Block a user