bake: name the five ways the extension can fail to answer, and move the landing verdict into a pure, tab-provable classifier
A no-answer stays a failure; it now says whether the extension never ran the landing, answered a stale generation, spoke a wire this build cannot read, cleared the request, or refused it.
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "core/wire/bake_wire.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "core/version/app_version.h"
|
||||
#include "core/wire/wire.h"
|
||||
|
||||
@@ -122,4 +124,49 @@ std::optional<BakeOutcome> decodeBakeOutcome(const std::string& wire) {
|
||||
return outcome;
|
||||
}
|
||||
|
||||
BakeAnswer classifyBakeAnswer(const std::optional<std::string>& raw,
|
||||
const BakeRequest& sent) {
|
||||
BakeAnswer answer;
|
||||
if (!raw || raw->empty()) {
|
||||
answer.kind = BakeAnswerKind::Cleared;
|
||||
return answer;
|
||||
}
|
||||
if (std::optional<BakeOutcome> outcome = decodeBakeOutcome(*raw)) {
|
||||
answer.kind = outcome->generation == sent.generation
|
||||
? BakeAnswerKind::Answered
|
||||
: BakeAnswerKind::ForeignOutcome;
|
||||
answer.outcome = std::move(outcome);
|
||||
return answer;
|
||||
}
|
||||
// Still a request: whether it is OURS is what separates "nothing read this key" from
|
||||
// "another instance overwrote it" — a persisted instanceGuid is copyable, so two
|
||||
// instances CAN name one key.
|
||||
if (const std::optional<BakeRequest> req = decodeBakeRequest(*raw)) {
|
||||
answer.kind =
|
||||
*req == sent ? BakeAnswerKind::Unanswered : BakeAnswerKind::ForeignRequest;
|
||||
return answer;
|
||||
}
|
||||
answer.kind = BakeAnswerKind::Undecodable;
|
||||
return answer;
|
||||
}
|
||||
|
||||
BakeScanVerdict classifyBakeScan(const BakeScanContext& session, const BakeScanKey& key,
|
||||
std::int64_t nowSec) {
|
||||
// Not a request: an outcome the writing instance has not collected yet, or a value
|
||||
// from a build we do not read. The writer owns clearing its own key.
|
||||
if (!key.decoded) return BakeScanVerdict::Ignore;
|
||||
|
||||
// Either direction, so a clock moved backwards is caught too.
|
||||
const std::int64_t age = nowSec - key.generation;
|
||||
if (age > kMaxRequestAgeSeconds || age < -kMaxRequestAgeSeconds)
|
||||
return BakeScanVerdict::ClearStale;
|
||||
|
||||
// Three tabs have to agree before anything may land: the tab the request was found in,
|
||||
// the tab the session's book/ledger last loaded, and the tab a persist will write into.
|
||||
// Landing on a disagreement writes one tab's bake into another's bank.
|
||||
const bool landable = session.sessionHasLoadedProject &&
|
||||
session.loadedProjectIsActive && key.inLoadedProject;
|
||||
return landable ? BakeScanVerdict::Land : BakeScanVerdict::RefuseWrongProject;
|
||||
}
|
||||
|
||||
} // namespace reasampler::wire
|
||||
|
||||
Reference in New Issue
Block a user