< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.InterpartsEngineController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/InterpartsEngineController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 24
Coverable lines: 24
Total lines: 70
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 12
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
Brands(...)100%210%
Offers(...)100%210%
Offer(...)100%210%
RunAsync()100%210%
ToResponse(...)0%156120%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/InterpartsEngineController.cs

#LineLine coverage
 1using Microsoft.AspNetCore.Authorization;
 2using Microsoft.AspNetCore.Mvc;
 3using Services.ApiServices.InterpartsEngine;
 4
 5namespace OzonOrdersWeb.Areas.Studio2.Controllers;
 6
 7/// <summary>
 8/// Проценка через движок Interparts: бренды по артикулу, предложения и перепроверка предложения.
 9/// Поиск может идти до ~2 минут, а nginx рвёт запрос через 60 с, поэтому запрос ждёт не дольше
 10/// <see cref="InterpartsEngineConfig.WebWaitSeconds"/> и отвечает 202 «ещё идёт»: поиск продолжается
 11/// в фоне (single-flight сервиса), повтор того же запроса подхватывает его или берёт готовый ответ из кэша.
 12/// </summary>
 13[Area("Studio2")]
 14[Authorize(Roles = "User,Admin")]
 15[Route("Studio2/InterpartsEngine")]
 16public sealed class InterpartsEngineController : Controller
 17{
 18    private readonly IInterpartsEngineService _engine;
 19    private readonly InterpartsEngineConfig _config;
 20
 021    public InterpartsEngineController(IInterpartsEngineService engine, InterpartsEngineConfig config)
 22    {
 023        _engine = engine;
 024        _config = config;
 025    }
 26
 27    [HttpGet("Brands")]
 28    public Task<IActionResult> Brands(string article, CancellationToken cancellationToken) =>
 029        RunAsync(ct => _engine.GetBrandsAsync(article, ct), cancellationToken);
 30
 31    [HttpGet("Offers")]
 32    public Task<IActionResult> Offers(string article, string brand, CancellationToken cancellationToken) =>
 033        RunAsync(ct => _engine.SearchOffersAsync(article, brand, ct), cancellationToken);
 34
 35    [HttpGet("Offer/{offerId}")]
 36    public Task<IActionResult> Offer(string offerId, CancellationToken cancellationToken) =>
 037        RunAsync(ct => _engine.RecheckOfferAsync(offerId, ct), cancellationToken);
 38
 39    private async Task<IActionResult> RunAsync<T>(Func<CancellationToken, Task<InterpartsEngineResult<T>>> call,
 40        CancellationToken requestAborted)
 41        where T : class
 42    {
 043        using var wait = CancellationTokenSource.CreateLinkedTokenSource(requestAborted);
 044        wait.CancelAfter(TimeSpan.FromSeconds(Math.Max(5, _config.WebWaitSeconds)));
 45        try
 46        {
 047            return ToResponse(await call(wait.Token));
 48        }
 049        catch (OperationCanceledException) when (!requestAborted.IsCancellationRequested)
 50        {
 051            return StatusCode(StatusCodes.Status202Accepted, new { pending = true });
 52        }
 053    }
 54
 55    private IActionResult ToResponse<T>(InterpartsEngineResult<T> result) where T : class
 56    {
 057        if (result.IsOk) return Json(result.Value);
 58
 059        var status = result.Status switch
 060        {
 061            InterpartsEngineStatus.NotFound => StatusCodes.Status404NotFound,
 062            InterpartsEngineStatus.Expired => StatusCodes.Status410Gone,
 063            _ when result.ErrorCode == "BAD_REQUEST" => StatusCodes.Status400BadRequest,
 064            _ when result.ErrorCode == "TIMEOUT" => StatusCodes.Status504GatewayTimeout,
 065            _ when result.Retry => StatusCodes.Status503ServiceUnavailable,
 066            _ => StatusCodes.Status502BadGateway
 067        };
 068        return StatusCode(status, new { code = result.ErrorCode, message = result.Message, retry = result.Retry });
 69    }
 70}