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)));
}
}
}
|