feat/dataset-detail-chart #5
|
|
@ -4,6 +4,8 @@ namespace geopro::net {
|
||||||
|
|
||||||
ApiBatch::ApiBatch(QList<IApiCall*> calls, Predicate isFailure, QObject* parent)
|
ApiBatch::ApiBatch(QList<IApiCall*> calls, Predicate isFailure, QObject* parent)
|
||||||
: QObject(parent), isFailure_(std::move(isFailure)) {
|
: QObject(parent), isFailure_(std::move(isFailure)) {
|
||||||
|
Q_ASSERT(!calls.isEmpty()); // 契约:至少一个 call(空 batch 永不发 succeeded,调用方会挂起)
|
||||||
|
Q_ASSERT(isFailure_); // 契约:必须提供失败谓词(否则首个 finished 即 bad_function_call)
|
||||||
responses_.resize(calls.size());
|
responses_.resize(calls.size());
|
||||||
remaining_ = static_cast<int>(calls.size());
|
remaining_ = static_cast<int>(calls.size());
|
||||||
for (int i = 0; i < calls.size(); ++i) {
|
for (int i = 0; i < calls.size(); ++i) {
|
||||||
|
|
@ -12,7 +14,7 @@ ApiBatch::ApiBatch(QList<IApiCall*> calls, Predicate isFailure, QObject* parent)
|
||||||
QObject::connect(c, &IApiCall::finished, this, [this, i](const ApiResponse& resp) {
|
QObject::connect(c, &IApiCall::finished, this, [this, i](const ApiResponse& resp) {
|
||||||
if (aborted_) return; // §5.0 入口守卫
|
if (aborted_) return; // §5.0 入口守卫
|
||||||
if (isFailure_(resp)) {
|
if (isFailure_(resp)) {
|
||||||
aborted_ = true;
|
aborted_ = true; // 此后 remaining_ 不再维护:迟到 finished 全被入口守卫挡掉
|
||||||
for (const auto& other : calls_) { // fail-fast:abort 其余在飞
|
for (const auto& other : calls_) { // fail-fast:abort 其余在飞
|
||||||
if (other) other->abort();
|
if (other) other->abort();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,14 @@ TEST(ApiBatch, SucceedsWhenAllOk) {
|
||||||
EXPECT_EQ(failSpy.count(), 0);
|
EXPECT_EQ(failSpy.count(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ApiBatch, SucceedsWithSingleCall) {
|
||||||
|
auto* a = new FakeApiCall;
|
||||||
|
auto* batch = new ApiBatch({a}, isFailure);
|
||||||
|
QSignalSpy okSpy(batch, &ApiBatch::succeeded);
|
||||||
|
a->fire(ok()); // N=1:一次 fire 即触发 --remaining_==0
|
||||||
|
EXPECT_EQ(okSpy.count(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ApiBatch, FailFastAbortsOthers) {
|
TEST(ApiBatch, FailFastAbortsOthers) {
|
||||||
auto* a = new FakeApiCall;
|
auto* a = new FakeApiCall;
|
||||||
auto* b = new FakeApiCall; // 慢的(永不 fire)
|
auto* b = new FakeApiCall; // 慢的(永不 fire)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue