mirror of
https://github.com/ZmnSCPxj/clboss.git
synced 2026-08-13 12:33:20 +02:00
XRebalancer: report the closest-to-delivery part as the failure reason
The transfer-failed/partial reason line took errors[0] -- the failed part with the lowest partid, which is just MCF's split index and tells you nothing about how close the cycle came. On a 10-part failure you would see a random part's from_target. Surface instead the part that got CLOSEST to delivery: the smallest from_target magnitude across errors[], with its node and failcode. That frontier -- how near the best attempt came and which node walled it -- is the informative number. Parse from_target=-N out of each error string, pick the minimum N; parts with no parseable from_target (non-204 fallbacks) sort last, and if none parse we keep the first error as before. The failcode rides along in the surfaced string, so a 0x100c fee-wall vs a 0x1007 liquidity-wall frontier stays distinguishable. When more than one part failed, the line notes [closest of N] so it is clear the number is the best of several, not the only one.
This commit is contained in:
parent
9fdfc130b4
commit
32ba879e6f
1 changed files with 44 additions and 5 deletions
|
|
@ -23,6 +23,7 @@
|
|||
#include"Util/make_unique.hpp"
|
||||
#include<algorithm>
|
||||
#include<ctime>
|
||||
#include<limits>
|
||||
#include<map>
|
||||
#include<random>
|
||||
#include<sstream>
|
||||
|
|
@ -705,16 +706,54 @@ private:
|
|||
<< " ppm)";
|
||||
ppm = os.str();
|
||||
}
|
||||
/* Chokepoint: the first error reason, if any, folded onto
|
||||
* the same line. */
|
||||
/* Chokepoint: among the failed parts, surface the one that got
|
||||
* CLOSEST to delivery -- the smallest from_target magnitude --
|
||||
* because that frontier (how near the best attempt came, and
|
||||
* the node that walled it) is the informative number, not
|
||||
* whichever part happens to carry the lowest partid. Parts
|
||||
* with no parseable from_target (non-204 fallbacks) sort last;
|
||||
* if none parse we keep the first. The failcode rides along in
|
||||
* the error string, so a 0x100c fee-wall vs 0x1007 liquidity-
|
||||
* wall frontier stays distinguishable. */
|
||||
auto reason = std::string();
|
||||
if (exec.is_object() && exec.has("errors")
|
||||
&& exec["errors"].is_array() && exec["errors"].size() > 0) {
|
||||
auto e0 = std::string(exec["errors"][std::size_t(0)]);
|
||||
for (auto& ch : e0)
|
||||
auto errs = exec["errors"];
|
||||
/* "from_target=-N" -> N; sentinel max if absent. */
|
||||
auto from_target_mag = [](std::string const& s) -> long {
|
||||
auto key = std::string("from_target=-");
|
||||
auto pos = s.find(key);
|
||||
if (pos == std::string::npos)
|
||||
return std::numeric_limits<long>::max();
|
||||
pos += key.size();
|
||||
auto n = 0L;
|
||||
auto any = false;
|
||||
while (pos < s.size()
|
||||
&& s[pos] >= '0' && s[pos] <= '9') {
|
||||
n = n * 10 + (s[pos] - '0');
|
||||
++pos;
|
||||
any = true;
|
||||
}
|
||||
return any ? n : std::numeric_limits<long>::max();
|
||||
};
|
||||
auto best_i = std::size_t(0);
|
||||
auto best = std::numeric_limits<long>::max();
|
||||
for (auto i = std::size_t(0); i < errs.size(); ++i) {
|
||||
auto m = from_target_mag(
|
||||
std::string(errs[i]));
|
||||
if (m < best) {
|
||||
best = m;
|
||||
best_i = i;
|
||||
}
|
||||
}
|
||||
auto e = std::string(errs[best_i]);
|
||||
for (auto& ch : e)
|
||||
if (ch == '\n' || ch == '\t')
|
||||
ch = ' ';
|
||||
reason = "; reason: " + e0;
|
||||
reason = "; reason: " + e;
|
||||
if (errs.size() > 1)
|
||||
reason += " [closest of "
|
||||
+ std::to_string(errs.size()) + "]";
|
||||
}
|
||||
if (delivered > 0.0)
|
||||
/* Full or partial delivery: settled/total parts and the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue