Lot V : « Pas avant des votes prouvés » (Yvv, 03/11) — un texte entré par des votes simulés est en vigueur sur le site, la publication attend que tout ce qui est en vigueur tienne sur les seuls votes prouvés (publish::waits_for_proven_votes, simulation::unproven), LD_PUBLISH_SIMULATED=1 publie quand même ; publication.waitsFor ; vu rouge puis vert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-11-03 05:42:13 +01:00
co-authored by Claude Opus 5.5
parent 0cde5bdbd0
commit 9b7345346e
7 changed files with 258 additions and 25 deletions
+46 -13
View File
@@ -137,23 +137,56 @@ pub async fn discard(state: &AppState, apply: bool) -> AppResult<Discarded> {
}
// The re-examination, the most recent entry first.
let adoptions = sqlx::query_as::<_, AdoptionRow>(
"SELECT id, proposal_id, unit_id, doc_id, kind, votes_for, votes_against, params, at FROM adoptions
ORDER BY at DESC, id DESC",
)
.fetch_all(&state.db)
.await?;
for a in adoptions {
let params: Value = serde_json::from_str(&a.params).unwrap_or(Value::Null);
let simulated = tally_of(&params["simulated"]);
// Without simulated votes, or examined by an act already: nothing to examine.
if simulated.cast() == 0 || !params["reexamined"].is_null() {
continue;
}
for (a, params, simulated) in to_examine(state, None).await? {
if let Some(r) = reexamine(state, &a, &params, simulated, apply).await? {
out.reexamined.push(r);
}
}
if apply {
// What waited for the proven votes may go out now (`publish::waits_for_proven_votes`).
sqlx::query("UPDATE outbox SET next_at = ? WHERE done_at IS NULL").bind(util::now()).execute(&state.db).await?;
state.publish_wake.notify_one();
}
Ok(out)
}
/// The entries into force still to examine, the most recent first: those that
/// counted simulated votes, not yet examined by an act — of one document, or all.
async fn to_examine(state: &AppState, doc_id: Option<&str>) -> AppResult<Vec<(AdoptionRow, Value, Tally)>> {
let adoptions = sqlx::query_as::<_, AdoptionRow>(
"SELECT id, proposal_id, unit_id, doc_id, kind, votes_for, votes_against, params, at FROM adoptions
WHERE ?1 IS NULL OR doc_id = ?1
ORDER BY at DESC, id DESC",
)
.bind(doc_id)
.fetch_all(&state.db)
.await?;
Ok(adoptions
.into_iter()
.filter_map(|a| {
let params: Value = serde_json::from_str(&a.params).unwrap_or(Value::Null);
let simulated = tally_of(&params["simulated"]);
// Without simulated votes, or examined by an act already: nothing to examine.
(simulated.cast() > 0 && params["reexamined"].is_null()).then_some((a, params, simulated))
})
.collect())
}
/// What, in effect in a document, entered by simulated votes and does not hold on
/// the proven votes alone: the re-examination of the act, told only — nothing is
/// written. Empty: everything in effect holds on the proven votes. The publication
/// waits on it (Yvv, 2026-11-03: « Pas avant des votes prouvés »,
/// `publish::waits_for_proven_votes`).
pub async fn unproven(state: &AppState, doc_id: &str) -> AppResult<Vec<Reexamined>> {
let mut out = Vec::new();
for (a, params, simulated) in to_examine(state, Some(doc_id)).await? {
if let Some(r) = reexamine(state, &a, &params, simulated, false).await?
&& r.in_effect
&& !r.holds
{
out.push(r);
}
}
Ok(out)
}