44 lines
1.6 KiB
C++
44 lines
1.6 KiB
C++
#include "ApiBatch.hpp"
|
||
|
||
namespace geopro::net {
|
||
|
||
ApiBatch::ApiBatch(QList<IApiCall*> calls, Predicate isFailure, QObject* parent)
|
||
: QObject(parent), isFailure_(std::move(isFailure)) {
|
||
Q_ASSERT(!calls.isEmpty()); // 契约:至少一个 call(空 batch 永不发 succeeded,调用方会挂起)
|
||
Q_ASSERT(isFailure_); // 契约:必须提供失败谓词(否则首个 finished 即 bad_function_call)
|
||
responses_.resize(calls.size());
|
||
remaining_ = static_cast<int>(calls.size());
|
||
for (int i = 0; i < calls.size(); ++i) {
|
||
IApiCall* c = calls[i];
|
||
calls_.append(c);
|
||
QObject::connect(c, &IApiCall::finished, this, [this, i](const ApiResponse& resp) {
|
||
if (aborted_) return; // §5.0 入口守卫
|
||
if (isFailure_(resp)) {
|
||
aborted_ = true; // 此后 remaining_ 不再维护:迟到 finished 全被入口守卫挡掉
|
||
for (const auto& other : calls_) { // fail-fast:abort 其余在飞
|
||
if (other) other->abort();
|
||
}
|
||
emit failed(i, resp);
|
||
deleteLater();
|
||
return;
|
||
}
|
||
responses_[i] = resp;
|
||
if (--remaining_ == 0) {
|
||
emit succeeded(responses_);
|
||
deleteLater();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
void ApiBatch::abort() {
|
||
if (aborted_) return;
|
||
aborted_ = true;
|
||
for (const auto& c : calls_) {
|
||
if (c) c->abort();
|
||
}
|
||
deleteLater();
|
||
}
|
||
|
||
} // namespace geopro::net
|