aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/tvmauth/client/misc/last_error.cpp
blob: b71f4d5bbbf973621a72590221950f8e10f749a2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "last_error.h" 
 
#include <util/string/builder.h> 
 
namespace NTvmAuth { 
    TLastError::TLastError() 
        : LastErrors_(MakeIntrusiveConst<TLastErrors>()) 
    { 
    } 
 
    TString TLastError::GetLastError(bool isOk, EType* type) const { 
        if (isOk) { 
            return OK_; 
        } 
 
        const TLastErrorsPtr ptr = LastErrors_.Get(); 
 
        for (const TLastErr& err : ptr->Errors) { 
            if (err && err->first == EType::NonRetriable) { 
                if (type) { 
                    *type = EType::NonRetriable; 
                } 
                return err->second; 
            } 
        } 
 
        for (const TLastErr& err : ptr->Errors) { 
            if (err) { 
                if (type) { 
                    *type = EType::Retriable; 
                } 
                return err->second; 
            } 
        } 
 
        if (type) { 
            *type = EType::NonRetriable; 
        } 
        return "Internal client error: failed to collect last useful error message, please report this message to tvm-dev@yandex-team.ru"; 
    } 
 
    TString TLastError::ProcessHttpError(TLastError::EScope scope, 
                                         TStringBuf path, 
                                         int code, 
                                         const TString& msg) const { 
        TString err = TStringBuilder() << "Path:" << path << ".Code=" << code << ": " << msg; 
 
        ProcessError(code >= 400 && code < 500 ? EType::NonRetriable 
                                               : EType::Retriable, 
                     scope, 
                     err); 
 
        return err; 
    } 
 
    void TLastError::ProcessError(TLastError::EType type, TLastError::EScope scope, const TStringBuf msg) const { 
        Update(scope, [&](TLastErr& lastError) { 
            if (lastError && lastError->first == EType::NonRetriable && type == EType::Retriable) { 
                return false; 
            } 
 
            TString err = TStringBuilder() << scope << ": " << msg; 
            err.erase(std::remove(err.begin(), err.vend(), '\r'), err.vend()); 
            std::replace(err.begin(), err.vend(), '\n', ' '); 
 
            lastError = {type, std::move(err)}; 
            return true; 
        }); 
    } 
 
    void TLastError::ClearError(TLastError::EScope scope) { 
        Update(scope, [&](TLastErr& lastError) { 
            if (!lastError) { 
                return false; 
            } 
 
            lastError.Clear(); 
            return true; 
        }); 
    } 
 
    void TLastError::ClearErrors() { 
        for (size_t idx = 0; idx < (size_t)EScope::COUNT; ++idx) { 
            ClearError((EScope)idx); 
        } 
    } 
 
    void TLastError::ThrowLastError() { 
        EType type; 
        TString err = GetLastError(false, &type); 
 
        switch (type) { 
            case EType::NonRetriable: 
                ythrow TNonRetriableException() 
                    << "Failed to start TvmClient. Do not retry: " 
                    << err; 
            case EType::Retriable: 
                ythrow TRetriableException() 
                    << "Failed to start TvmClient. You can retry: " 
                    << err; 
        } 
    } 
 
    template <typename Func> 
    void TLastError::Update(TLastError::EScope scope, Func func) const { 
        Y_VERIFY(scope != EScope::COUNT); 
 
        TLastErrors errs = *LastErrors_.Get(); 
        TLastErr& lastError = errs.Errors[(size_t)scope]; 
 
        if (func(lastError)) { 
            LastErrors_.Set(MakeIntrusiveConst<TLastErrors>(std::move(errs))); 
        } 
    } 
}