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:
@@ -83,18 +83,29 @@ pub async fn pass(state: &AppState) -> anyhow::Result<()> {
|
||||
let rows: Vec<&Due> = due.iter().filter(|d| d.doc_id == doc_id).collect();
|
||||
let last = rows.iter().map(|d| d.id).max().unwrap_or(0);
|
||||
let attempts = rows.iter().map(|d| d.attempts).max().unwrap_or(0);
|
||||
if waits_for_a_text(state, &doc_id).await? {
|
||||
if let Some(wait) = waits(state, &doc_id).await? {
|
||||
// Not a failure: no attempt counted, no error. The queue stays; the first
|
||||
// text that enters queues a row due now, and everything goes out with it.
|
||||
// text that enters queues a row due now, and everything goes out with it —
|
||||
// or, waiting for proven votes, it is asked again a while later.
|
||||
let again = match wait {
|
||||
Wait::Text => MAX_BACKOFF_SECS,
|
||||
Wait::Proven => PROVEN_AGAIN_SECS,
|
||||
};
|
||||
sqlx::query("UPDATE outbox SET next_at = ? WHERE doc_id = ? AND done_at IS NULL")
|
||||
.bind(util::in_seconds(MAX_BACKOFF_SECS))
|
||||
.bind(util::in_seconds(again))
|
||||
.bind(&doc_id)
|
||||
.execute(&state.db)
|
||||
.await?;
|
||||
tracing::info!(
|
||||
doc = %doc_id, waiting = rows.len(),
|
||||
"publication suspended: no article in force, the queue waits for the first text (LD_PUBLISH_WITHOUT_ARTICLES=1 publishes anyway)"
|
||||
);
|
||||
match wait {
|
||||
Wait::Text => tracing::info!(
|
||||
doc = %doc_id, waiting = rows.len(),
|
||||
"publication suspended: no article in force, the queue waits for the first text (LD_PUBLISH_WITHOUT_ARTICLES=1 publishes anyway)"
|
||||
),
|
||||
Wait::Proven => tracing::info!(
|
||||
doc = %doc_id, waiting = rows.len(),
|
||||
"publication suspended: something in effect entered by simulated votes does not hold on the proven votes (LD_PUBLISH_SIMULATED=1 publishes anyway)"
|
||||
),
|
||||
}
|
||||
continue;
|
||||
}
|
||||
match publish_doc(state, &doc_id).await {
|
||||
@@ -123,6 +134,58 @@ pub async fn pass(state: &AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Why a document waits before it is published.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Wait {
|
||||
/// None of its articles is in force (ADR 0011).
|
||||
Text,
|
||||
/// Something in effect entered by simulated votes and does not hold on the
|
||||
/// proven votes alone (ADR 0012).
|
||||
Proven,
|
||||
}
|
||||
|
||||
impl Wait {
|
||||
/// As the API says it (`publication.waitsFor`).
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Text => "text",
|
||||
Self::Proven => "proven",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Waiting for proven votes, the queue is asked again this often: a proven vote that
|
||||
/// carries an entry already in force queues nothing by itself.
|
||||
const PROVEN_AGAIN_SECS: i64 = 600;
|
||||
|
||||
/// Does the document wait before it is published, and for what: a first text
|
||||
/// (`waits_for_a_text`), then proven votes (`waits_for_proven_votes`).
|
||||
pub async fn waits(state: &AppState, doc_id: &str) -> anyhow::Result<Option<Wait>> {
|
||||
if waits_for_a_text(state, doc_id).await? {
|
||||
return Ok(Some(Wait::Text));
|
||||
}
|
||||
if waits_for_proven_votes(state, doc_id).await? {
|
||||
return Ok(Some(Wait::Proven));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Does the document wait for proven votes before it is published? Yvv, 2026-11-03:
|
||||
/// « Pas avant des votes prouvés ». A text — an order, a title, a level of inertia, a
|
||||
/// removal — that entered by simulated votes is in force on the site, and sends
|
||||
/// nothing to the repository of the texts while anything in effect that entered by
|
||||
/// simulated votes does not hold on the proven votes alone, by the re-examination of
|
||||
/// the act « supprime » (`simulation::unproven`, told only). The chain being closed,
|
||||
/// nothing goes out of Monnaie libre before it opens. The one place of this rule;
|
||||
/// `LD_PUBLISH_SIMULATED=1` publishes anyway (`Publish::simulated`).
|
||||
pub async fn waits_for_proven_votes(state: &AppState, doc_id: &str) -> anyhow::Result<bool> {
|
||||
if state.cfg.publish.as_ref().is_none_or(|p| p.simulated) {
|
||||
return Ok(false);
|
||||
}
|
||||
let unproven = crate::simulation::unproven(state, doc_id).await.map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
Ok(!unproven.is_empty())
|
||||
}
|
||||
|
||||
/// Does the document wait for a text before it is published? Yes when none of its
|
||||
/// articles is in force — the seed proposals are not (ADR 0011) — unless the
|
||||
/// publication is told to go out anyway (`LD_PUBLISH_WITHOUT_ARTICLES`). The default is
|
||||
|
||||
Reference in New Issue
Block a user