| | | 1 | | using System.Diagnostics; |
| | | 2 | | using Syki.Back.Domain.Enums; |
| | | 3 | | using Syki.Back.Domain.Institutions; |
| | | 4 | | |
| | | 5 | | namespace Syki.Back.Commands.Domain.Commands; |
| | | 6 | | |
| | | 7 | | public class Command |
| | | 8 | | { |
| | 304 | 9 | | public int Id { get; set; } |
| | 36 | 10 | | public int InstitutionId { get; set; } |
| | 1216 | 11 | | public string Type { get; set; } |
| | 608 | 12 | | public string Data { get; set; } |
| | 304 | 13 | | public CommandStatus Status { get; set; } |
| | 304 | 14 | | public DateTime CreatedAt { get; set; } |
| | 304 | 15 | | public int Duration { get; set; } |
| | 304 | 16 | | public DateTime? ProcessedAt { get; set; } |
| | 0 | 17 | | public Guid? ProcessorId { get; set; } |
| | 608 | 18 | | public string? Error { get; set; } |
| | | 19 | | |
| | | 20 | | /// <summary> |
| | | 21 | | /// Id do comando que gerou o comando |
| | | 22 | | /// Utilizado quando um comando gera outro em seu handler |
| | | 23 | | /// </summary> |
| | 304 | 24 | | public int? ParentId { get; set; } |
| | | 25 | | |
| | | 26 | | /// <summary> |
| | | 27 | | /// Id do comando com erro que gerou o comando atual |
| | | 28 | | /// Utilizado quando o comando original está com erro e é reprocessado |
| | | 29 | | /// O comando atual é uma cópia do original (imutabilidade) |
| | | 30 | | /// </summary> |
| | 304 | 31 | | public int? OriginalId { get; set; } |
| | | 32 | | |
| | | 33 | | /// <summary> |
| | | 34 | | /// Id do lote que contém o comando |
| | | 35 | | /// </summary> |
| | 304 | 36 | | public int? BatchId { get; set; } |
| | | 37 | | |
| | 304 | 38 | | public DateTime? NotBefore { get; set; } |
| | | 39 | | |
| | 912 | 40 | | public string? ActivityId { get; set; } |
| | | 41 | | |
| | | 42 | | /// <summary> |
| | | 43 | | /// Número máximo de tentativas de reprocessamento automático do comando. |
| | | 44 | | /// Quando o comando falha e MaxRetries > 0, um novo comando de retry é criado com MaxRetries - 1. |
| | | 45 | | /// </summary> |
| | 306 | 46 | | public int MaxRetries { get; set; } |
| | | 47 | | |
| | | 48 | | /// <summary> |
| | | 49 | | /// Which retry attempt this is. 0 for the original command, 1 for first retry, etc. |
| | | 50 | | /// </summary> |
| | 0 | 51 | | public int RetryAttempt { get; set; } |
| | | 52 | | |
| | | 53 | | /// <summary> |
| | | 54 | | /// Backoff strategy for computing delay between retries. |
| | | 55 | | /// When None (default), retries are immediate. |
| | | 56 | | /// </summary> |
| | 304 | 57 | | public BackoffStrategy BackoffStrategy { get; set; } |
| | | 58 | | |
| | | 59 | | /// <summary> |
| | | 60 | | /// Base delay in seconds used by the backoff formula. Default is 5. |
| | | 61 | | /// </summary> |
| | 304 | 62 | | public int BaseDelaySeconds { get; set; } |
| | | 63 | | |
| | 914 | 64 | | public List<string> Logs { get; set; } = []; |
| | | 65 | | |
| | 268 | 66 | | public Institution? Institution { get; set; } |
| | | 67 | | |
| | 612 | 68 | | public Command() { } |
| | | 69 | | |
| | 268 | 70 | | public Command( |
| | 268 | 71 | | Institution institution, |
| | 268 | 72 | | object data, |
| | 268 | 73 | | int? parentId = null, |
| | 268 | 74 | | int? originalId = null, |
| | 268 | 75 | | int? batchId = null, |
| | 268 | 76 | | int? delaySeconds = null, |
| | 268 | 77 | | string? activityId = null, |
| | 268 | 78 | | int maxRetries = 0, |
| | 268 | 79 | | BackoffStrategy backoffStrategy = BackoffStrategy.None, |
| | 268 | 80 | | int baseDelaySeconds = 5 |
| | 268 | 81 | | ) { |
| | 268 | 82 | | Institution = institution; |
| | 268 | 83 | | Type = data.GetType().Name; |
| | 268 | 84 | | Data = data.Serialize(); |
| | 268 | 85 | | CreatedAt = DateTime.UtcNow; |
| | 268 | 86 | | ParentId = parentId; |
| | 268 | 87 | | OriginalId = originalId; |
| | 268 | 88 | | BatchId = batchId; |
| | 268 | 89 | | ActivityId = activityId; |
| | 268 | 90 | | NotBefore = delaySeconds != null ? DateTime.UtcNow.AddSeconds(delaySeconds.Value) : null; |
| | 268 | 91 | | MaxRetries = maxRetries; |
| | 268 | 92 | | BackoffStrategy = backoffStrategy; |
| | 268 | 93 | | BaseDelaySeconds = baseDelaySeconds; |
| | 268 | 94 | | } |
| | | 95 | | |
| | 36 | 96 | | public Command( |
| | 36 | 97 | | int institutionId, |
| | 36 | 98 | | object data, |
| | 36 | 99 | | int? parentId = null, |
| | 36 | 100 | | int? originalId = null, |
| | 36 | 101 | | int? batchId = null, |
| | 36 | 102 | | int? delaySeconds = null, |
| | 36 | 103 | | string? activityId = null, |
| | 36 | 104 | | int maxRetries = 0, |
| | 36 | 105 | | BackoffStrategy backoffStrategy = BackoffStrategy.None, |
| | 36 | 106 | | int baseDelaySeconds = 5 |
| | 36 | 107 | | ) { |
| | 36 | 108 | | InstitutionId = institutionId; |
| | 36 | 109 | | Type = data.GetType().Name; |
| | 36 | 110 | | Data = data.Serialize(); |
| | 36 | 111 | | CreatedAt = DateTime.UtcNow; |
| | 36 | 112 | | ParentId = parentId; |
| | 36 | 113 | | OriginalId = originalId; |
| | 36 | 114 | | BatchId = batchId; |
| | 36 | 115 | | ActivityId = activityId; |
| | 36 | 116 | | NotBefore = delaySeconds != null ? DateTime.UtcNow.AddSeconds(delaySeconds.Value) : null; |
| | 36 | 117 | | MaxRetries = maxRetries; |
| | 36 | 118 | | BackoffStrategy = backoffStrategy; |
| | 36 | 119 | | BaseDelaySeconds = baseDelaySeconds; |
| | 36 | 120 | | } |
| | | 121 | | |
| | | 122 | | public void SetAwaiting() |
| | | 123 | | { |
| | 0 | 124 | | Status = CommandStatus.Awaiting; |
| | 0 | 125 | | } |
| | | 126 | | |
| | | 127 | | public void Processed(double duration) |
| | | 128 | | { |
| | 304 | 129 | | ProcessedAt = DateTime.UtcNow; |
| | 304 | 130 | | Duration = Convert.ToInt32(duration); |
| | 304 | 131 | | Status = Error.HasValue() ? CommandStatus.Error : CommandStatus.Success; |
| | 304 | 132 | | } |
| | | 133 | | |
| | | 134 | | public ActivityContext GetParentActivityContext() |
| | | 135 | | { |
| | 304 | 136 | | ActivityContext.TryParse(ActivityId, null, out var parsedContext); |
| | 304 | 137 | | return parsedContext; |
| | | 138 | | } |
| | | 139 | | } |