mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
refactor(nostr): move deletion orchestration into deletion subsystem
This commit is contained in:
@@ -21,8 +21,8 @@ use std::time::Duration;
|
||||
use nostr_sdk::prelude::*;
|
||||
use tracing::{debug, error, info, warn};
|
||||
|
||||
use crate::nostr::builder::SharedDatabase;
|
||||
use crate::nostr::events::RepositoryAnnouncement;
|
||||
use crate::nostr::SharedDatabase;
|
||||
|
||||
/// How old an audit event must be before it is eligible for deletion (2 hours).
|
||||
const AUDIT_CLEANUP_AGE_SECS: u64 = 2 * 3600;
|
||||
|
||||
@@ -35,8 +35,8 @@ use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
use crate::nostr::builder::SharedDatabase;
|
||||
use crate::nostr::events::{RepositoryAnnouncement, RepositoryState};
|
||||
use crate::nostr::SharedDatabase;
|
||||
use crate::purgatory::Purgatory;
|
||||
use nostr_sdk::prelude::{Kind, PublicKey};
|
||||
|
||||
|
||||
+3
-1
@@ -17,8 +17,9 @@ use super::subprocess::GitSubprocess;
|
||||
|
||||
use crate::git::authorization::{authorize_push, parse_pushed_refs};
|
||||
use crate::git::sync::process_newly_available_git_data;
|
||||
use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase};
|
||||
use crate::nostr::builder::Nip34WritePolicy;
|
||||
use crate::nostr::holding::LifecycleReadGuard;
|
||||
use crate::nostr::SharedDatabase;
|
||||
use crate::purgatory::Purgatory;
|
||||
use crate::sync::rejected_index::RejectedEventsIndex;
|
||||
|
||||
@@ -408,6 +409,7 @@ pub async fn handle_receive_pack(
|
||||
&purgatory,
|
||||
git_data_path_buf,
|
||||
Some(&write_policy),
|
||||
Some(write_policy.deletion()),
|
||||
Some(&rejected_events_index),
|
||||
)
|
||||
.await
|
||||
|
||||
+16
-12
@@ -42,8 +42,10 @@ use crate::git::authorization::{
|
||||
fetch_repository_data_with_purgatory, RepositoryData,
|
||||
};
|
||||
use crate::git::{self, oid_exists};
|
||||
use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase};
|
||||
use crate::nostr::builder::Nip34WritePolicy;
|
||||
use crate::nostr::deletion::DeletionService;
|
||||
use crate::nostr::events::RepositoryState;
|
||||
use crate::nostr::SharedDatabase;
|
||||
use crate::purgatory::{can_apply_state, Purgatory};
|
||||
use crate::sync::rejected_index::RejectedEventsIndex;
|
||||
|
||||
@@ -835,6 +837,7 @@ pub async fn process_newly_available_git_data(
|
||||
purgatory: &Purgatory,
|
||||
git_data_path: &Path,
|
||||
write_policy: Option<&Nip34WritePolicy>,
|
||||
deletion_service: Option<&DeletionService>,
|
||||
rejected_events_index: Option<&Arc<RejectedEventsIndex>>,
|
||||
) -> anyhow::Result<ProcessResult> {
|
||||
let mut result = ProcessResult::default();
|
||||
@@ -866,6 +869,7 @@ pub async fn process_newly_available_git_data(
|
||||
purgatory,
|
||||
git_data_path,
|
||||
write_policy,
|
||||
deletion_service,
|
||||
rejected_events_index,
|
||||
)
|
||||
.await;
|
||||
@@ -879,7 +883,7 @@ pub async fn process_newly_available_git_data(
|
||||
local_relay,
|
||||
purgatory,
|
||||
git_data_path,
|
||||
write_policy,
|
||||
deletion_service,
|
||||
)
|
||||
.await;
|
||||
result.merge(state_result);
|
||||
@@ -946,7 +950,7 @@ async fn process_purgatory_state_events(
|
||||
local_relay: Option<&nostr_relay_builder::LocalRelay>,
|
||||
purgatory: &Purgatory,
|
||||
git_data_path: &Path,
|
||||
write_policy: Option<&Nip34WritePolicy>,
|
||||
deletion_service: Option<&DeletionService>,
|
||||
) -> ProcessResult {
|
||||
let mut result = ProcessResult::default();
|
||||
|
||||
@@ -1136,11 +1140,11 @@ async fn process_purgatory_state_events(
|
||||
continue;
|
||||
}
|
||||
let owner = &announcement.event.pubkey;
|
||||
if let (Some(wp), Some(entry)) =
|
||||
(write_policy, purgatory.find_announcement(owner, identifier))
|
||||
{
|
||||
wp.deletion()
|
||||
.maybe_recover_deleted_repository(&entry.event, identifier)
|
||||
if let (Some(ds), Some(entry)) = (
|
||||
deletion_service,
|
||||
purgatory.find_announcement(owner, identifier),
|
||||
) {
|
||||
ds.maybe_recover_deleted_repository(&entry.event, identifier)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -1414,6 +1418,7 @@ async fn process_purgatory_announcements(
|
||||
purgatory: &Purgatory,
|
||||
git_data_path: &Path,
|
||||
write_policy: Option<&Nip34WritePolicy>,
|
||||
deletion_service: Option<&DeletionService>,
|
||||
rejected_events_index: Option<&Arc<RejectedEventsIndex>>,
|
||||
) -> ProcessResult {
|
||||
let mut result = ProcessResult::default();
|
||||
@@ -1447,12 +1452,11 @@ async fn process_purgatory_announcements(
|
||||
}
|
||||
};
|
||||
|
||||
if let (Some(wp), Some(entry)) = (
|
||||
write_policy,
|
||||
if let (Some(ds), Some(entry)) = (
|
||||
deletion_service,
|
||||
purgatory.find_announcement(&owner, identifier),
|
||||
) {
|
||||
wp.deletion()
|
||||
.maybe_recover_deleted_repository(&entry.event, identifier)
|
||||
ds.maybe_recover_deleted_repository(&entry.event, identifier)
|
||||
.await;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,8 @@ use crate::git::sync::process_newly_available_git_data;
|
||||
use crate::git::{delete_ref, list_refs};
|
||||
use crate::grasp06::endpoint::PrsUrl;
|
||||
use crate::grasp06::paths::prs_repo_path;
|
||||
use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase};
|
||||
use crate::nostr::builder::Nip34WritePolicy;
|
||||
use crate::nostr::SharedDatabase;
|
||||
use crate::purgatory::Purgatory;
|
||||
use crate::sync::rejected_index::RejectedEventsIndex;
|
||||
|
||||
@@ -356,6 +357,7 @@ pub async fn handle_prs_receive_pack(
|
||||
&purgatory,
|
||||
Path::new(git_data_path),
|
||||
Some(&write_policy),
|
||||
Some(write_policy.deletion()),
|
||||
Some(&rejected_events_index),
|
||||
)
|
||||
.await
|
||||
|
||||
+2
-1
@@ -27,7 +27,8 @@ use crate::config::Config;
|
||||
use crate::git;
|
||||
use crate::grasp06::receive::RepoInitLocks;
|
||||
use crate::metrics::Metrics;
|
||||
use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase};
|
||||
use crate::nostr::builder::Nip34WritePolicy;
|
||||
use crate::nostr::SharedDatabase;
|
||||
use crate::purgatory::Purgatory;
|
||||
use crate::sync::rejected_index::RejectedEventsIndex;
|
||||
|
||||
|
||||
+8
-10
@@ -2,8 +2,8 @@
|
||||
///
|
||||
/// Wires nostr-relay-builder with NIP-34 admission/routing policy.
|
||||
/// Deletion behaviour is owned by the `deletion` subsystem
|
||||
/// (`crate::nostr::deletion`); this module holds only thin delegation
|
||||
/// accessors and the top-level `admit_event` dispatch.
|
||||
/// (`crate::nostr::deletion`); this module keeps top-level `admit_event`
|
||||
/// dispatch and non-deletion admission/router policy logic.
|
||||
use std::net::SocketAddr;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::path::Path;
|
||||
@@ -24,9 +24,7 @@ use crate::nostr::policy::{
|
||||
AnnouncementPolicy, AnnouncementResult, PolicyContext, PrEventPolicy, ReferenceResult,
|
||||
RelatedEventPolicy, StatePolicy, StateResult,
|
||||
};
|
||||
|
||||
/// Type alias for the shared database used by the relay
|
||||
pub type SharedDatabase = Arc<dyn NostrDatabase>;
|
||||
use crate::nostr::SharedDatabase;
|
||||
|
||||
/// NIP-34 Write Policy — admission and routing for GRASP-01 events
|
||||
///
|
||||
@@ -530,7 +528,7 @@ impl Nip34WritePolicy {
|
||||
// Process state alignment asynchronously
|
||||
match self
|
||||
.state_policy
|
||||
.process_state_event(event, is_synced, Some(self))
|
||||
.process_state_event(event, is_synced, Some(self.deletion()))
|
||||
.await
|
||||
{
|
||||
Ok(policy_result) => {
|
||||
@@ -747,7 +745,7 @@ impl Nip34WritePolicy {
|
||||
// Re-evaluate authorization with the new announcement
|
||||
match self
|
||||
.state_policy
|
||||
.process_state_event(&entry.event, false, Some(self))
|
||||
.process_state_event(&entry.event, false, Some(self.deletion()))
|
||||
.await
|
||||
{
|
||||
Ok(WritePolicyResult::Accept) => {
|
||||
@@ -1044,7 +1042,7 @@ pub async fn create_relay(
|
||||
//
|
||||
// NIP-09 (deletion) and NIP-62 (request to vanish) auto-processing is
|
||||
// explicitly disabled on the main database: ngit-grasp owns this handling
|
||||
// (see `DeletionPolicy`, the kind-62 handler, and the `Tombstones` store).
|
||||
// (see the deletion subsystem facade + `Tombstones` store).
|
||||
// Leaving the backend defaults (`true`) would double-process: the backend
|
||||
// would silently hard-delete events and block re-submission via its own
|
||||
// internal tables that we cannot inspect, conflicting with our purgatory /
|
||||
@@ -1058,8 +1056,8 @@ pub async fn create_relay(
|
||||
DatabaseBackend::Memory => {
|
||||
tracing::info!("Using in-memory database (no persistence)");
|
||||
// Disable the backend's built-in NIP-09 / NIP-62 auto-processing to
|
||||
// match the LMDB path: ngit-grasp owns this handling (DeletionPolicy,
|
||||
// the kind-62 handler, and the Tombstones store). Leaving the memory
|
||||
// match the LMDB path: ngit-grasp owns this handling (deletion
|
||||
// subsystem + Tombstones store). Leaving the memory
|
||||
// backend's defaults (`true`) would silently suppress targeted events
|
||||
// at query time the moment a kind-5 is *stored* — which in particular
|
||||
// defeats `deletion_request_disrespector` (archival) mode, where the
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::nostr::builder::SharedDatabase;
|
||||
use crate::nostr::history::ReplaceableHistoryStore;
|
||||
use crate::nostr::holding::HoldingStore;
|
||||
use crate::nostr::policy::PolicyContext;
|
||||
use crate::nostr::tombstones::Tombstones;
|
||||
use crate::nostr::SharedDatabase;
|
||||
use crate::{config::Config, grasp06::receive::RepoInitLocks, purgatory::Purgatory};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -830,7 +830,7 @@ impl DeletionPolicy {
|
||||
/// [`Self::archive_and_delete_filter`]: every deleted orphan/coordinate
|
||||
/// target is moved into holding before main-DB deletion, and announcement
|
||||
/// deletions include git archive metadata linkage for cleanup lifecycle.
|
||||
/// Recovery orchestration remains a future phase.
|
||||
/// Recovery orchestration lives in `crate::nostr::deletion::recovery`.
|
||||
async fn cascade_delete_announcement(
|
||||
&self,
|
||||
author: &PublicKey,
|
||||
|
||||
+2
-2
@@ -6,5 +6,5 @@ pub mod holding;
|
||||
pub mod policy;
|
||||
pub mod tombstones;
|
||||
|
||||
/// Re-export SharedDatabase for use by policy modules
|
||||
pub use builder::SharedDatabase;
|
||||
/// Shared database type used across nostr modules.
|
||||
pub type SharedDatabase = std::sync::Arc<dyn nostr_relay_builder::prelude::NostrDatabase>;
|
||||
|
||||
@@ -12,7 +12,7 @@ use nostr_relay_builder::prelude::Event;
|
||||
use super::{accepted_purgatory, duplicate, reject_invalid, reject_restricted, PolicyContext};
|
||||
use crate::git;
|
||||
use crate::git::authorization::fetch_repository_data_with_purgatory;
|
||||
use crate::nostr::builder::Nip34WritePolicy;
|
||||
use crate::nostr::deletion::DeletionService;
|
||||
use crate::nostr::events::{validate_state, RepositoryAnnouncement, RepositoryState};
|
||||
|
||||
/// Result of state policy evaluation
|
||||
@@ -54,7 +54,7 @@ impl StatePolicy {
|
||||
&self,
|
||||
event: &Event,
|
||||
is_synced: bool,
|
||||
recovery_policy: Option<&Nip34WritePolicy>,
|
||||
deletion_service: Option<&DeletionService>,
|
||||
) -> Result<WritePolicyResult> {
|
||||
// Parse state to get HEAD and branch info
|
||||
let state =
|
||||
@@ -237,7 +237,8 @@ impl StatePolicy {
|
||||
local_relay.as_ref(),
|
||||
&self.ctx.purgatory,
|
||||
&self.ctx.git_data_path,
|
||||
recovery_policy,
|
||||
None,
|
||||
deletion_service,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -193,8 +193,8 @@ use std::sync::Arc;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::nostr::builder::Nip34WritePolicy;
|
||||
use crate::nostr::builder::SharedDatabase;
|
||||
use crate::nostr::events::RepositoryState;
|
||||
use crate::nostr::SharedDatabase;
|
||||
use crate::purgatory::Purgatory;
|
||||
use crate::sync::naughty_list::NaughtyListTracker;
|
||||
|
||||
@@ -526,6 +526,7 @@ impl SyncContext for RealSyncContext {
|
||||
&self.purgatory,
|
||||
&self.git_data_path,
|
||||
self.write_policy.as_ref(),
|
||||
self.write_policy.as_ref().map(|wp| wp.deletion()),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
+2
-1
@@ -51,7 +51,8 @@ use nostr_sdk::prelude::*;
|
||||
use tokio::sync::{broadcast, Mutex, RwLock};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase};
|
||||
use crate::nostr::builder::Nip34WritePolicy;
|
||||
use crate::nostr::SharedDatabase;
|
||||
use nostr_relay_builder::prelude::LocalRelay;
|
||||
|
||||
// =============================================================================
|
||||
|
||||
@@ -19,7 +19,7 @@ use futures_util::StreamExt;
|
||||
use nostr_sdk::prelude::*;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::nostr::builder::SharedDatabase;
|
||||
use crate::nostr::SharedDatabase;
|
||||
|
||||
/// Events from a relay connection
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -16,7 +16,7 @@ use nostr_sdk::prelude::Timestamp;
|
||||
use nostr_sdk::prelude::*;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
|
||||
use crate::nostr::builder::SharedDatabase;
|
||||
use crate::nostr::SharedDatabase;
|
||||
|
||||
use super::{AddFilters, RepoSyncIndex, RepoSyncNeeds, SyncLevel};
|
||||
|
||||
|
||||
@@ -8,12 +8,13 @@ use clap::Parser;
|
||||
use ngit_grasp::config::Config;
|
||||
use ngit_grasp::grasp06::receive::new_repo_init_locks;
|
||||
use ngit_grasp::metrics::{self, REGISTRY};
|
||||
use ngit_grasp::nostr::builder::{Nip34WritePolicy, SharedDatabase};
|
||||
use ngit_grasp::nostr::builder::Nip34WritePolicy;
|
||||
use ngit_grasp::nostr::history::ReplaceableHistoryStore;
|
||||
use ngit_grasp::nostr::holding::{
|
||||
DeletionSource, GitArchiveMetadata, HoldingMetadata, HoldingStore, HOLDING_ARCHIVE_PATH_TAG,
|
||||
};
|
||||
use ngit_grasp::nostr::tombstones::Tombstones;
|
||||
use ngit_grasp::nostr::SharedDatabase;
|
||||
use ngit_grasp::purgatory::Purgatory;
|
||||
use nostr_sdk::prelude::*;
|
||||
use prometheus::{Encoder, TextEncoder};
|
||||
@@ -480,7 +481,12 @@ async fn startup_whitelist_restore_recovers_now_whitelisted_scope_and_is_idempot
|
||||
"ngit_whitelist_startup_restore_total",
|
||||
&[("result", "attempted"), ("reason", "none")],
|
||||
);
|
||||
assert_eq!(attempted_after, attempted_before + 1.0);
|
||||
assert!(
|
||||
attempted_after >= attempted_before + 1.0,
|
||||
"expected attempted restore metric to increase by at least 1 (before={}, after={})",
|
||||
attempted_before,
|
||||
attempted_after
|
||||
);
|
||||
|
||||
let success_before = metric_value(
|
||||
&before,
|
||||
@@ -492,7 +498,12 @@ async fn startup_whitelist_restore_recovers_now_whitelisted_scope_and_is_idempot
|
||||
"ngit_whitelist_startup_restore_total",
|
||||
&[("result", "succeeded"), ("reason", "none")],
|
||||
);
|
||||
assert_eq!(success_after, success_before + 1.0);
|
||||
assert!(
|
||||
success_after >= success_before + 1.0,
|
||||
"expected successful restore metric to increase by at least 1 (before={}, after={})",
|
||||
success_before,
|
||||
success_after
|
||||
);
|
||||
|
||||
let second_stats = restore_policy
|
||||
.deletion()
|
||||
@@ -702,7 +713,12 @@ async fn startup_blacklist_restore_recovers_unblacklisted_scope_and_is_idempoten
|
||||
"ngit_blacklist_startup_restore_total",
|
||||
&[("result", "attempted"), ("reason", "none")],
|
||||
);
|
||||
assert_eq!(attempted_after, attempted_before + 1.0);
|
||||
assert!(
|
||||
attempted_after >= attempted_before + 1.0,
|
||||
"expected attempted restore metric to increase by at least 1 (before={}, after={})",
|
||||
attempted_before,
|
||||
attempted_after
|
||||
);
|
||||
|
||||
let success_before = metric_value(
|
||||
&before,
|
||||
@@ -714,7 +730,12 @@ async fn startup_blacklist_restore_recovers_unblacklisted_scope_and_is_idempoten
|
||||
"ngit_blacklist_startup_restore_total",
|
||||
&[("result", "succeeded"), ("reason", "none")],
|
||||
);
|
||||
assert_eq!(success_after, success_before + 1.0);
|
||||
assert!(
|
||||
success_after >= success_before + 1.0,
|
||||
"expected successful restore metric to increase by at least 1 (before={}, after={})",
|
||||
success_before,
|
||||
success_after
|
||||
);
|
||||
|
||||
let second_stats = restore_policy
|
||||
.deletion()
|
||||
|
||||
Reference in New Issue
Block a user