feat(sms): Twilio SmsNotificationDeliveryAdapter + classifier + options + DI (S3)
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.NotificationOutbox;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration options for the SMS (Twilio-REST) notification delivery adapter,
|
||||
/// bound from the <c>ScadaBridge:Sms</c> configuration section.
|
||||
///
|
||||
/// SMS connection settings are primarily carried by the deployed
|
||||
/// <c>SmsConfiguration</c> entity. These values supply the documented fallbacks /
|
||||
/// caps used by the central Notification Outbox's
|
||||
/// <c>SmsNotificationDeliveryAdapter</c>: <see cref="MaxMessageLength"/> caps the
|
||||
/// composed body, and <see cref="ConnectionTimeoutSeconds"/> is the per-request
|
||||
/// timeout used when the deployed <c>SmsConfiguration.ConnectionTimeoutSeconds</c>
|
||||
/// field is left unset (non-positive) — a value present on the row always takes
|
||||
/// precedence.
|
||||
/// </summary>
|
||||
public sealed class SmsOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum length of the composed SMS body; longer bodies are truncated with an
|
||||
/// ellipsis before the Twilio POST. Default 1600 (Twilio's per-message maximum).
|
||||
/// Must be strictly positive.
|
||||
/// </summary>
|
||||
public int MaxMessageLength { get; set; } = 1600;
|
||||
|
||||
/// <summary>
|
||||
/// Per-request connection/response timeout (seconds) used when the deployed
|
||||
/// <c>SmsConfiguration.ConnectionTimeoutSeconds</c> is unset (non-positive).
|
||||
/// Default 30s. Must be strictly positive.
|
||||
/// </summary>
|
||||
public int ConnectionTimeoutSeconds { get; set; } = 30;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates <see cref="SmsOptions"/> on startup. A non-positive
|
||||
/// <see cref="SmsOptions.MaxMessageLength"/> would truncate every body to nothing,
|
||||
/// and a non-positive <see cref="SmsOptions.ConnectionTimeoutSeconds"/> would make
|
||||
/// the per-request timeout meaningless, so both are required to be strictly positive.
|
||||
/// </summary>
|
||||
public sealed class SmsOptionsValidator : IValidateOptions<SmsOptions>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ValidateOptionsResult Validate(string? name, SmsOptions options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
var failures = new List<string>();
|
||||
|
||||
if (options.MaxMessageLength <= 0)
|
||||
{
|
||||
failures.Add(
|
||||
$"ScadaBridge:Sms:{nameof(SmsOptions.MaxMessageLength)} ({options.MaxMessageLength}) " +
|
||||
"must be > 0; it caps the composed SMS body length.");
|
||||
}
|
||||
|
||||
if (options.ConnectionTimeoutSeconds <= 0)
|
||||
{
|
||||
failures.Add(
|
||||
$"ScadaBridge:Sms:{nameof(SmsOptions.ConnectionTimeoutSeconds)} ({options.ConnectionTimeoutSeconds}) " +
|
||||
"must be > 0; it is the per-request Twilio timeout fallback.");
|
||||
}
|
||||
|
||||
return failures.Count > 0
|
||||
? ValidateOptionsResult.Fail(failures)
|
||||
: ValidateOptionsResult.Success;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user