ServiceRequestStatusService
Documentație pentru serviciul ServiceRequestStatusService
1. Descriere Generală
ServiceRequestStatusService
este un serviciu specializat pentru verificarea statusului cererilor de servicii individuale. Spre deosebire de RequestStatusService
care poate returna mai multe rezultate, acest serviciu este optimizat pentru verificarea unei singure cereri cu informații detaliate.
Caracteristici principale: - Verificare status pentru o cerere specifică - Returnare informații detaliate despre cerere - Integrare cu componenta FodServiceRequestStatus - Comunicare HTTP cu API-ul de verificare - Suport pentru verificare prin multiple identificatori
2. Configurare și Înregistrare
// Program.cs sau Startup.cs
builder.Services.AddHttpClient<IServiceRequestStatusService, ServiceRequestStatusService>(client =>
{
client.BaseAddress = new Uri(configuration["ApiSettings:BaseUrl"]);
client.Timeout = TimeSpan.FromSeconds(30);
});
// Pentru implementare server-side cu acces direct la DB
builder.Services.AddScoped<IServiceRequestStatusService, ServerServiceRequestStatusService>();
3. Interfața IServiceRequestStatusService
public interface IServiceRequestStatusService
{
Task<ServiceRequestStatusResponseModel> Check(ServiceRequestStatusRequestModel request);
}
4. Metode Disponibile
Metodă | Parametri | Return | Descriere |
---|---|---|---|
Check |
ServiceRequestStatusRequestModel request |
Task<ServiceRequestStatusResponseModel> |
Verifică statusul unei cereri specifice |
5. Modele de Date
ServiceRequestStatusRequestModel (parametri verificare)
public class ServiceRequestStatusRequestModel
{
public string RequestNumber { get; set; }
public string VerificationCode { get; set; }
public string IDNP { get; set; }
public string Email { get; set; }
}
ServiceRequestStatusResponseModel (rezultat)
public class ServiceRequestStatusResponseModel
{
// Informații generale
public string RequestNumber { get; set; }
public string ServiceName { get; set; }
public string ServiceCode { get; set; }
public DateTime SubmissionDate { get; set; }
public DateTime? EstimatedCompletionDate { get; set; }
public DateTime? ActualCompletionDate { get; set; }
// Status
public string Status { get; set; }
public string StatusCode { get; set; }
public string StatusDescription { get; set; }
public int StatusPercentage { get; set; }
// Detalii solicitant
public string ApplicantName { get; set; }
public string ApplicantType { get; set; }
// Cost și plată
public decimal TotalCost { get; set; }
public bool IsPaid { get; set; }
public DateTime? PaymentDate { get; set; }
public string PaymentMethod { get; set; }
// Documente
public List<DocumentInfo> SubmittedDocuments { get; set; }
public List<DocumentInfo> ResultDocuments { get; set; }
// Livrare
public string DeliveryMethod { get; set; }
public string DeliveryStatus { get; set; }
public DeliveryAddress DeliveryAddress { get; set; }
// Istoric
public List<StatusHistoryItem> StatusHistory { get; set; }
// Informații adiționale
public string ProcessingOffice { get; set; }
public string ResponsiblePerson { get; set; }
public string Notes { get; set; }
public bool CanBeCancelled { get; set; }
public bool CanBeModified { get; set; }
}
6. Exemple de Utilizare
Verificare simplă cu număr cerere
@inject IServiceRequestStatusService StatusService
<FodServiceRequestStatus
RequestNumber="@requestNumber"
VerificationCode="@verificationCode" />
<!-- Sau implementare manuală -->
<FodCard>
<FodCardContent>
<FodText Typo="Typo.h6" GutterBottom="true">
Verificare status cerere
</FodText>
<FodTextField @bind-Value="checkModel.RequestNumber"
Label="Număr cerere"
Required="true" />
<FodTextField @bind-Value="checkModel.VerificationCode"
Label="Cod verificare"
Required="true" />
<FodButton OnClick="CheckStatus"
Color="FodColor.Primary"
Disabled="@isChecking">
Verifică
</FodButton>
@if (statusResult != null)
{
<FodServiceRequestStatusResponse Status="@statusResult" />
}
</FodCardContent>
</FodCard>
@code {
private ServiceRequestStatusRequestModel checkModel = new();
private ServiceRequestStatusResponseModel statusResult;
private bool isChecking;
private async Task CheckStatus()
{
isChecking = true;
try
{
statusResult = await StatusService.Check(checkModel);
}
catch (Exception ex)
{
NotificationService.ShowError("Eroare la verificarea statusului");
}
finally
{
isChecking = false;
}
}
}
Pagină dedicată pentru tracking
@page "/cerere/{RequestNumber}/{VerificationCode}"
@inject IServiceRequestStatusService StatusService
<FodContainer>
@if (isLoading)
{
<FodLoadingLinear Indeterminate="true" />
}
else if (status == null)
{
<FodAlert Severity="Severity.Error">
Cererea nu a fost găsită sau datele de verificare sunt incorecte
</FodAlert>
}
else
{
<FodText Typo="Typo.h4" GutterBottom="true">
Status cerere: @status.RequestNumber
</FodText>
<FodGrid Container="true" Spacing="3">
<!-- Informații principale -->
<FodGrid Item="true" xs="12" md="8">
<FodCard>
<FodCardContent>
<!-- Progress vizual -->
<FodStepper ActiveStep="@GetProgressStep()"
Orientation="Orientation.Horizontal">
<FodStep>
<StepLabel>Depusă</StepLabel>
</FodStep>
<FodStep>
<StepLabel>În verificare</StepLabel>
</FodStep>
<FodStep>
<StepLabel>În procesare</StepLabel>
</FodStep>
<FodStep>
<StepLabel>Finalizată</StepLabel>
</FodStep>
</FodStepper>
<!-- Status curent -->
<div class="mt-4">
<FodAlert Severity="@GetStatusSeverity()">
<FodAlertTitle>@status.Status</FodAlertTitle>
@status.StatusDescription
</FodAlert>
</div>
<!-- Detalii cerere -->
<FodList Class="mt-3">
<FodListItem>
<FodText>Serviciu:</FodText>
<FodText Class="ms-auto">@status.ServiceName</FodText>
</FodListItem>
<FodListItem>
<FodText>Data depunerii:</FodText>
<FodText Class="ms-auto">
@status.SubmissionDate.ToString("dd.MM.yyyy HH:mm")
</FodText>
</FodListItem>
@if (status.EstimatedCompletionDate.HasValue)
{
<FodListItem>
<FodText>Termen estimat:</FodText>
<FodText Class="ms-auto">
@status.EstimatedCompletionDate.Value.ToString("dd.MM.yyyy")
</FodText>
</FodListItem>
}
</FodList>
</FodCardContent>
</FodCard>
<!-- Istoric status -->
@if (status.StatusHistory?.Any() == true)
{
<FodCard Class="mt-3">
<FodCardContent>
<FodText Typo="Typo.h6" GutterBottom="true">
Istoric modificări
</FodText>
<FodTimeline>
@foreach (var history in status.StatusHistory.OrderByDescending(h => h.Date))
{
<FodTimelineItem>
<FodTimelineSeparator>
<FodTimelineDot Color="@GetHistoryColor(history.Status)" />
<FodTimelineConnector />
</FodTimelineSeparator>
<FodTimelineContent>
<FodText Typo="Typo.caption">
@history.Date.ToString("dd.MM.yyyy HH:mm")
</FodText>
<FodText Typo="Typo.body2">
@history.Status
</FodText>
@if (!string.IsNullOrEmpty(history.Notes))
{
<FodText Typo="Typo.caption" Color="FodColor.Secondary">
@history.Notes
</FodText>
}
</FodTimelineContent>
</FodTimelineItem>
}
</FodTimeline>
</FodCardContent>
</FodCard>
}
</FodGrid>
<!-- Panou lateral -->
<FodGrid Item="true" xs="12" md="4">
<!-- Cost și plată -->
<FodCard>
<FodCardContent>
<FodText Typo="Typo.h6" GutterBottom="true">
Informații plată
</FodText>
<FodText Typo="Typo.h5" Color="FodColor.Primary">
@status.TotalCost MDL
</FodText>
@if (status.IsPaid)
{
<FodChip Color="FodColor.Success"
Size="FodSize.Small"
Icon="@FodIcons.Material.Filled.CheckCircle">
Achitat
</FodChip>
@if (status.PaymentDate.HasValue)
{
<FodText Typo="Typo.caption" Class="mt-2">
Plătit la: @status.PaymentDate.Value.ToString("dd.MM.yyyy")
</FodText>
}
}
else
{
<FodButton Color="FodColor.Primary"
Variant="FodVariant.Filled"
FullWidth="true"
Class="mt-2">
Achită acum
</FodButton>
}
</FodCardContent>
</FodCard>
<!-- Documente -->
@if (status.ResultDocuments?.Any() == true)
{
<FodCard Class="mt-3">
<FodCardContent>
<FodText Typo="Typo.h6" GutterBottom="true">
Documente rezultat
</FodText>
<FodList Dense="true">
@foreach (var doc in status.ResultDocuments)
{
<FodListItem>
<FodIcon Icon="@FodIcons.Material.Filled.Description"
Size="FodSize.Small"
Class="me-2" />
<FodLink Href="@doc.DownloadUrl">
@doc.Name
</FodLink>
</FodListItem>
}
</FodList>
</FodCardContent>
</FodCard>
}
<!-- Acțiuni -->
<FodCard Class="mt-3">
<FodCardContent>
<FodText Typo="Typo.h6" GutterBottom="true">
Acțiuni disponibile
</FodText>
<div class="d-grid gap-2">
<FodButton Variant="FodVariant.Outlined"
OnClick="PrintStatus">
<FodIcon Icon="@FodIcons.Material.Filled.Print"
Class="me-2" />
Printează status
</FodButton>
@if (status.CanBeCancelled)
{
<FodButton Color="FodColor.Error"
Variant="FodVariant.Outlined"
OnClick="CancelRequest">
Anulează cererea
</FodButton>
}
<FodButton Variant="FodVariant.Text"
OnClick="ContactSupport">
Contactează suport
</FodButton>
</div>
</FodCardContent>
</FodCard>
</FodGrid>
</FodGrid>
}
</FodContainer>
@code {
[Parameter] public string RequestNumber { get; set; }
[Parameter] public string VerificationCode { get; set; }
private ServiceRequestStatusResponseModel status;
private bool isLoading = true;
protected override async Task OnInitializedAsync()
{
await LoadStatus();
}
private async Task LoadStatus()
{
var request = new ServiceRequestStatusRequestModel
{
RequestNumber = RequestNumber,
VerificationCode = VerificationCode
};
try
{
status = await StatusService.Check(request);
}
catch
{
// Eroare gestionată în UI
}
finally
{
isLoading = false;
}
}
}
Widget pentru monitorizare multiplă
<FodCard>
<FodCardContent>
<FodText Typo="Typo.h6" GutterBottom="true">
Monitorizare cereri active
</FodText>
@foreach (var request in activeRequests)
{
<RequestStatusWidget Request="@request" />
}
</FodCardContent>
</FodCard>
@code {
public class RequestStatusWidget : ComponentBase
{
[Parameter] public TrackedRequest Request { get; set; }
[Inject] private IServiceRequestStatusService StatusService { get; set; }
private ServiceRequestStatusResponseModel currentStatus;
private bool isLoading = true;
protected override async Task OnInitializedAsync()
{
var checkRequest = new ServiceRequestStatusRequestModel
{
RequestNumber = Request.Number,
VerificationCode = Request.Code
};
try
{
currentStatus = await StatusService.Check(checkRequest);
}
finally
{
isLoading = false;
}
}
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
if (isLoading)
{
builder.OpenComponent<FodSkeleton>(0);
builder.AddAttribute(1, "Type", SkeletonType.Text);
builder.CloseComponent();
return;
}
builder.OpenElement(0, "div");
builder.AddAttribute(1, "class", "status-widget mb-3 p-3 border rounded");
// Header
builder.OpenElement(2, "div");
builder.AddAttribute(3, "class", "d-flex justify-content-between align-items-center");
builder.OpenComponent<FodText>(4);
builder.AddAttribute(5, "Typo", Typo.subtitle2);
builder.AddAttribute(6, "ChildContent", (RenderFragment)((b) =>
b.AddContent(7, currentStatus?.ServiceName)));
builder.CloseComponent();
builder.OpenComponent<FodChip>(8);
builder.AddAttribute(9, "Size", FodSize.Small);
builder.AddAttribute(10, "Color", GetStatusColor());
builder.AddAttribute(11, "ChildContent", (RenderFragment)((b) =>
b.AddContent(12, currentStatus?.Status)));
builder.CloseComponent();
builder.CloseElement(); // div
// Progress bar
builder.OpenComponent<FodLoadingLinear>(13);
builder.AddAttribute(14, "Value", currentStatus?.StatusPercentage ?? 0);
builder.AddAttribute(15, "Color", GetStatusColor());
builder.AddAttribute(16, "Class", "mt-2");
builder.CloseComponent();
builder.CloseElement(); // div
}
private FodColor GetStatusColor()
{
return currentStatus?.StatusCode switch
{
"COMPLETED" => FodColor.Success,
"PROCESSING" => FodColor.Primary,
"REJECTED" => FodColor.Error,
_ => FodColor.Default
};
}
}
}
Notificări push pentru schimbări status
@implements IDisposable
@inject IServiceRequestStatusService StatusService
@inject INotificationService NotificationService
<NotificationEnabledStatusChecker
RequestNumber="@RequestNumber"
VerificationCode="@VerificationCode"
OnStatusChanged="HandleStatusChange" />
@code {
public class NotificationEnabledStatusChecker : ComponentBase, IDisposable
{
[Parameter] public string RequestNumber { get; set; }
[Parameter] public string VerificationCode { get; set; }
[Parameter] public EventCallback<ServiceRequestStatusResponseModel> OnStatusChanged { get; set; }
[Inject] private IServiceRequestStatusService StatusService { get; set; }
private Timer checkTimer;
private string lastStatusCode;
protected override async Task OnInitializedAsync()
{
// Check inițial
await CheckStatus();
// Setup polling la fiecare minut
checkTimer = new Timer(async _ => await CheckStatusWithNotification(),
null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}
private async Task CheckStatus()
{
var request = new ServiceRequestStatusRequestModel
{
RequestNumber = RequestNumber,
VerificationCode = VerificationCode
};
var status = await StatusService.Check(request);
lastStatusCode = status?.StatusCode;
}
private async Task CheckStatusWithNotification()
{
var request = new ServiceRequestStatusRequestModel
{
RequestNumber = RequestNumber,
VerificationCode = VerificationCode
};
var status = await StatusService.Check(request);
if (status?.StatusCode != lastStatusCode)
{
// Status schimbat
await InvokeAsync(async () =>
{
await OnStatusChanged.InvokeAsync(status);
// Notificare
await NotificationService.ShowAsync(new NotificationOptions
{
Title = "Status actualizat",
Body = $"Cererea {RequestNumber} are un nou status: {status.Status}",
Icon = "/icon-192.png",
RequireInteraction = true
});
});
lastStatusCode = status.StatusCode;
}
}
public void Dispose()
{
checkTimer?.Dispose();
}
}
}
7. Gestionarea Erorilor
public class ErrorHandlingServiceRequestStatusService : IServiceRequestStatusService
{
private readonly IServiceRequestStatusService _innerService;
private readonly ILogger<ErrorHandlingServiceRequestStatusService> _logger;
public async Task<ServiceRequestStatusResponseModel> Check(
ServiceRequestStatusRequestModel request)
{
try
{
return await _innerService.Check(request);
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
_logger.LogWarning("Cererea {RequestNumber} nu a fost găsită",
request.RequestNumber);
return null;
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.Unauthorized)
{
throw new UnauthorizedException(
"Date de verificare incorecte pentru cererea specificată");
}
catch (TaskCanceledException)
{
throw new TimeoutException(
"Verificarea statusului a durat prea mult. Încercați din nou.");
}
}
}
8. Cache și Optimizare
public class CachedServiceRequestStatusService : IServiceRequestStatusService
{
private readonly IServiceRequestStatusService _innerService;
private readonly IMemoryCache _cache;
private readonly ILogger<CachedServiceRequestStatusService> _logger;
public async Task<ServiceRequestStatusResponseModel> Check(
ServiceRequestStatusRequestModel request)
{
var cacheKey = $"ServiceStatus_{request.RequestNumber}_{request.VerificationCode}";
// Cache mai scurt pentru statusuri în procesare
var cacheOptions = new MemoryCacheEntryOptions();
if (_cache.TryGetValue<ServiceRequestStatusResponseModel>(cacheKey, out var cached))
{
// Verificare dacă trebuie reîmprospătat
if (ShouldRefresh(cached))
{
_cache.Remove(cacheKey);
}
else
{
_logger.LogDebug("Returnare status din cache pentru {RequestNumber}",
request.RequestNumber);
return cached;
}
}
var result = await _innerService.Check(request);
if (result != null)
{
// Cache timp diferit bazat pe status
var cacheTime = result.StatusCode switch
{
"COMPLETED" => TimeSpan.FromHours(24),
"REJECTED" => TimeSpan.FromHours(24),
"PROCESSING" => TimeSpan.FromMinutes(5),
_ => TimeSpan.FromMinutes(15)
};
_cache.Set(cacheKey, result, cacheTime);
}
return result;
}
private bool ShouldRefresh(ServiceRequestStatusResponseModel cached)
{
// Reîmprospătare pentru statusuri active
return cached.StatusCode is "PROCESSING" or "PENDING" or "VERIFICATION";
}
}
9. Audit și Logging
public class AuditedServiceRequestStatusService : IServiceRequestStatusService
{
private readonly IServiceRequestStatusService _innerService;
private readonly IAuditService _auditService;
private readonly IHttpContextAccessor _httpContextAccessor;
public async Task<ServiceRequestStatusResponseModel> Check(
ServiceRequestStatusRequestModel request)
{
var userId = _httpContextAccessor.HttpContext?.User?.Identity?.Name;
var ipAddress = _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
// Audit request
await _auditService.LogAsync(new AuditEntry
{
Action = "ServiceRequestStatusCheck",
UserId = userId,
IpAddress = ipAddress,
Details = new
{
RequestNumber = request.RequestNumber,
HasVerificationCode = !string.IsNullOrEmpty(request.VerificationCode),
Timestamp = DateTime.UtcNow
}
});
try
{
var result = await _innerService.Check(request);
// Audit result
await _auditService.LogAsync(new AuditEntry
{
Action = "ServiceRequestStatusCheckResult",
UserId = userId,
Details = new
{
RequestNumber = request.RequestNumber,
Found = result != null,
Status = result?.StatusCode
}
});
return result;
}
catch (Exception ex)
{
// Audit error
await _auditService.LogAsync(new AuditEntry
{
Action = "ServiceRequestStatusCheckError",
UserId = userId,
Details = new
{
RequestNumber = request.RequestNumber,
Error = ex.Message
}
});
throw;
}
}
}
10. Validare și Securitate
public class SecureServiceRequestStatusService : IServiceRequestStatusService
{
private readonly IServiceRequestStatusService _innerService;
private readonly IValidator<ServiceRequestStatusRequestModel> _validator;
private readonly IRateLimiter _rateLimiter;
public async Task<ServiceRequestStatusResponseModel> Check(
ServiceRequestStatusRequestModel request)
{
// Validare
var validationResult = await _validator.ValidateAsync(request);
if (!validationResult.IsValid)
{
throw new ValidationException(validationResult.Errors);
}
// Rate limiting
var rateLimitKey = $"StatusCheck_{request.RequestNumber}";
if (!await _rateLimiter.AllowAsync(rateLimitKey, 10, TimeSpan.FromMinute))
{
throw new RateLimitExceededException(
"Prea multe verificări pentru această cerere. Încercați mai târziu.");
}
// Sanitizare input
request.RequestNumber = request.RequestNumber?.Trim().ToUpperInvariant();
request.VerificationCode = request.VerificationCode?.Trim();
return await _innerService.Check(request);
}
}
public class ServiceRequestStatusRequestValidator
: AbstractValidator<ServiceRequestStatusRequestModel>
{
public ServiceRequestStatusRequestValidator()
{
RuleFor(x => x.RequestNumber)
.NotEmpty().WithMessage("Numărul cererii este obligatoriu")
.Matches(@"^[A-Z]{3}-\d{4}-\d{6}$")
.WithMessage("Format număr cerere invalid");
RuleFor(x => x.VerificationCode)
.NotEmpty().When(x => string.IsNullOrEmpty(x.IDNP))
.WithMessage("Cod verificare sau IDNP obligatoriu");
RuleFor(x => x.IDNP)
.Matches(@"^\d{13}$").When(x => !string.IsNullOrEmpty(x.IDNP))
.WithMessage("IDNP invalid");
}
}
11. Testare
[TestClass]
public class ServiceRequestStatusServiceTests
{
private Mock<HttpMessageHandler> _httpHandler;
private IServiceRequestStatusService _service;
[TestInitialize]
public void Setup()
{
_httpHandler = new Mock<HttpMessageHandler>();
var httpClient = new HttpClient(_httpHandler.Object)
{
BaseAddress = new Uri("https://api.test.com")
};
_service = new ServiceRequestStatusService(httpClient);
}
[TestMethod]
public async Task Check_ValidRequest_ReturnsStatus()
{
// Arrange
var request = new ServiceRequestStatusRequestModel
{
RequestNumber = "REQ-2024-123456",
VerificationCode = "ABC123"
};
var expectedResponse = new ServiceRequestStatusResponseModel
{
RequestNumber = "REQ-2024-123456",
Status = "În procesare",
StatusCode = "PROCESSING",
StatusPercentage = 50
};
SetupHttpResponse(expectedResponse);
// Act
var result = await _service.Check(request);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual("PROCESSING", result.StatusCode);
Assert.AreEqual(50, result.StatusPercentage);
}
[TestMethod]
public async Task Check_InvalidRequest_ReturnsNull()
{
// Arrange
var request = new ServiceRequestStatusRequestModel
{
RequestNumber = "INVALID",
VerificationCode = "WRONG"
};
SetupHttpResponse(HttpStatusCode.NotFound);
// Act
var result = await _service.Check(request);
// Assert
Assert.IsNull(result);
}
}
12. Integrare cu SignalR pentru actualizări real-time
public class RealTimeServiceRequestStatusService : IServiceRequestStatusService
{
private readonly IServiceRequestStatusService _innerService;
private readonly IHubContext<StatusHub> _hubContext;
public async Task<ServiceRequestStatusResponseModel> Check(
ServiceRequestStatusRequestModel request)
{
var result = await _innerService.Check(request);
if (result != null)
{
// Subscribe pentru actualizări
await _hubContext.Groups.AddToGroupAsync(
Context.ConnectionId,
$"request-{request.RequestNumber}");
// Trimite status inițial
await _hubContext.Clients.Caller.SendAsync(
"StatusUpdate", result);
}
return result;
}
}
public class StatusHub : Hub
{
public async Task SubscribeToRequest(string requestNumber, string verificationCode)
{
// Validare
if (IsValidSubscription(requestNumber, verificationCode))
{
await Groups.AddToGroupAsync(Context.ConnectionId, $"request-{requestNumber}");
}
}
public async Task UnsubscribeFromRequest(string requestNumber)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"request-{requestNumber}");
}
}
13. Best Practices
- Validare strictă - Validați format număr cerere și cod verificare
- Rate limiting - Preveniți abuzul prin verificări repetate
- Cache inteligent - Cache diferențiat pe status
- Audit complet - Logați toate verificările pentru securitate
- Erori clare - Mesaje specifice pentru diferite scenarii
- Real-time updates - Considerați SignalR pentru actualizări live
14. Monitorizare și Metrici
public class MonitoredServiceRequestStatusService : IServiceRequestStatusService
{
private readonly IServiceRequestStatusService _innerService;
private readonly IMetrics _metrics;
public async Task<ServiceRequestStatusResponseModel> Check(
ServiceRequestStatusRequestModel request)
{
using var activity = Activity.StartActivity("ServiceRequestStatus.Check");
activity?.SetTag("request.number", request.RequestNumber);
var timer = Stopwatch.StartNew();
try
{
var result = await _innerService.Check(request);
_metrics.Measure.Counter.Increment("service_request_status_check",
new MetricTags("found", result != null ? "true" : "false"));
if (result != null)
{
_metrics.Measure.Counter.Increment("service_request_by_status",
new MetricTags("status", result.StatusCode));
}
return result;
}
catch (Exception ex)
{
_metrics.Measure.Counter.Increment("service_request_status_error",
new MetricTags("error_type", ex.GetType().Name));
throw;
}
finally
{
_metrics.Measure.Timer.Time("service_request_status_duration",
timer.ElapsedMilliseconds);
}
}
}
15. Concluzie
ServiceRequestStatusService
oferă o interfață specializată pentru verificarea detaliată a statusului cererilor individuale. Cu suport pentru cache inteligent, validare strictă și posibilități de extindere pentru notificări real-time, serviciul asigură o experiență optimă pentru monitorizarea cererilor în sistemul FOD.