| | | 1 | | using System.Threading.Channels; |
| | | 2 | | using ArturRios.Heimdall.Command.Services; |
| | | 3 | | |
| | | 4 | | namespace ArturRios.Heimdall.WebApi.Email; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// The in-process queue between UC-47's handler and <see cref="RegistrationDispatcher" />. Bounded, |
| | | 8 | | /// never blocks the caller. Shaped exactly like <see cref="PasswordRecoveryQueue" />, whose remarks |
| | | 9 | | /// explain why it is in memory rather than a response-time floor or a database outbox. |
| | | 10 | | /// </summary> |
| | | 11 | | /// <remarks> |
| | | 12 | | /// Unlike the recovery queue it holds a secret — a password hash and salt — for the seconds a |
| | | 13 | | /// request waits. It is never written anywhere, and a restart drops it with the request, which the |
| | | 14 | | /// caller simply repeats. |
| | | 15 | | /// </remarks> |
| | 899 | 16 | | public sealed class RegistrationQueue(ILogger<RegistrationQueue> logger) : IRegistrationQueue |
| | | 17 | | { |
| | | 18 | | /// <summary>Requests held at most while the dispatcher catches up.</summary> |
| | | 19 | | public const int Capacity = 1024; |
| | | 20 | | |
| | 899 | 21 | | private readonly Channel<RegistrationRequest> _channel = Channel.CreateBounded<RegistrationRequest>( |
| | 899 | 22 | | new BoundedChannelOptions(Capacity) |
| | 899 | 23 | | { |
| | 899 | 24 | | // Wait, not one of the Drop modes: see PasswordRecoveryQueue. |
| | 899 | 25 | | FullMode = BoundedChannelFullMode.Wait, |
| | 899 | 26 | | SingleReader = true |
| | 899 | 27 | | }); |
| | | 28 | | |
| | | 29 | | /// <summary>The dispatcher's end of the queue.</summary> |
| | 899 | 30 | | public ChannelReader<RegistrationRequest> Reader => _channel.Reader; |
| | | 31 | | |
| | | 32 | | public bool TryEnqueue(RegistrationRequest request) |
| | | 33 | | { |
| | 20 | 34 | | if (_channel.Writer.TryWrite(request)) |
| | | 35 | | { |
| | 20 | 36 | | return true; |
| | | 37 | | } |
| | | 38 | | |
| | | 39 | | // No address in the log (NFR-22). |
| | 0 | 40 | | logger.LogWarning( |
| | 0 | 41 | | "The registration queue is full ({Capacity}); a registration request was dropped", Capacity); |
| | | 42 | | |
| | 0 | 43 | | return false; |
| | | 44 | | } |
| | | 45 | | } |