fix: prune only after stored state promotion

This commit is contained in:
DanConwayDev
2026-07-30 11:41:16 +01:00
parent a8b1e657eb
commit 945b712bb8
4 changed files with 20 additions and 13 deletions
+3 -2
View File
@@ -10,8 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Removed superseded same-author repository states from purgatory after their
replacement is promoted when the pushed Git data cannot reconstruct them.
Reconstructable rollback states and other maintainers' states are retained.
replacement is promoted when the locally available Git data cannot
reconstruct them. Reconstructable rollback states and other maintainers'
states are retained.
## [2.0.0] - 2026-07-27
+4 -3
View File
@@ -442,9 +442,10 @@ sequenceDiagram
State promotion remains oldest-first so reconstructable predecessors reach
relay history before a newer replacement. After a promotion pass, purgatory
removes only older events on the promoted event's exact coordinate (same author
and `d` tag) when their Git objects are still unavailable. Reconstructable
predecessors and other maintainers' states remain as rollback candidates.
removes only non-preferred events on the promoted event's exact coordinate
(same author and `d` tag) when their Git objects are still unavailable.
Reconstructable predecessors and other maintainers' states remain as rollback
candidates.
### PR Event Arrival (Kind 1617/1618)
+6 -5
View File
@@ -35,7 +35,7 @@ use std::process::Command;
use tracing::{debug, info, warn};
use async_trait::async_trait;
use nostr_sdk::prelude::Event;
use nostr_sdk::prelude::{Event, SaveEventStatus};
use crate::git::authorization::{
collect_authorized_maintainers, fetch_repository_data_excluding_purgatory,
@@ -863,7 +863,7 @@ async fn save_promoted_event(
event: &Event,
context: PurgatorySaveContext,
promotion_hooks: Option<&dyn PurgatoryPromotionHooks>,
) -> anyhow::Result<()> {
) -> anyhow::Result<SaveEventStatus> {
if let Some(hooks) = promotion_hooks {
hooks.before_event_saved(event, context).await;
}
@@ -871,7 +871,6 @@ async fn save_promoted_event(
database
.save_event(event)
.await
.map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to save promoted event {}: {e}", event.id))
}
@@ -1210,7 +1209,7 @@ async fn process_purgatory_state_events(
)
.await
{
Ok(_) => {
Ok(save_status) => {
info!(
identifier = %identifier,
event_id = %entry.event.id,
@@ -1236,7 +1235,9 @@ async fn process_purgatory_state_events(
// Remove from purgatory
purgatory.remove_state_event(identifier, &entry.event.id);
result.states_released += 1;
promoted_states.push(entry.event.clone());
if save_status.is_success() {
promoted_states.push(entry.event.clone());
}
// Add the newly saved state to db_repo_data so subsequent iterations
// can correctly determine if they're the latest
+7 -3
View File
@@ -640,15 +640,19 @@ impl Purgatory {
}
}
/// Remove older states on coordinates promoted in this pass when their Git
/// objects are still unavailable. Reconstructable predecessors and states
/// from other authors remain available as rollback candidates.
/// Remove non-preferred states on coordinates promoted in this pass when
/// their Git objects are still unavailable. Reconstructable predecessors
/// and states from other authors remain available as rollback candidates.
pub(crate) fn remove_unreconstructable_state_replacements(
&self,
identifier: &str,
promoted: &[Event],
source_repo_path: &Path,
) -> usize {
if promoted.is_empty() {
return 0;
}
let is_preferred = |candidate: &Event, current: &Event| {
candidate.created_at > current.created_at
|| (candidate.created_at == current.created_at && candidate.id < current.id)