diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-23 11:17:10 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-23 12:05:29 +0000 |
| commit | 70749ea9df1f6061c332112c617b615f91d79d48 (patch) | |
| tree | 6f4ace061681d8356ea79eb782fddb36c1f31d23 /src/http/mod.rs | |
| parent | 9f15929b10825c2f55434a98794fc551794cad2b (diff) | |
fix: re-process hot-cache maintainer announcements after git push promotion
When an owner announcement is promoted from purgatory via a git push,
any maintainer announcements sitting in the rejected_events_index hot
cache were never re-processed. The invalidate_and_get call only existed
in SyncManager::process_event_static (the nostr sync path); the git push
promotion path (http -> handlers -> git::sync) had no access to the
rejected_events_index at all.
Thread rejected_events_index and write_policy through the git push path:
- process_purgatory_announcements: after saving the promoted announcement,
parse its maintainers tag and call invalidate_and_get() for each, then
re-process any returned hot-cache events via admit_event + save
- process_newly_available_git_data: accept optional write_policy and
rejected_events_index, pass them through to process_purgatory_announcements
- handle_receive_pack: accept Arc<Nip34WritePolicy> and
Arc<RejectedEventsIndex>, pass them to process_newly_available_git_data
- HttpService / run_server: carry the two new fields, clone into each
handle_receive_pack call
- main.rs: obtain rejected_events_index from sync_manager before moving
it into its task; wrap write_policy in Arc for the HTTP server
- RealSyncContext::process_newly_available_git_data: pass None for both
new params (purgatory sync path already handles this via
SyncManager::process_event_static)
Also rewrite the maintainer_reprocessing integration tests to correctly
exercise the hot-cache path now that announcements require git data
before being released from purgatory:
- Start relay_b with relay_a as bootstrap so its SyncManager syncs
maintainer announcements via negentropy before the owner git push
- Use push_unique_git_data_to_relay (new helper) to give each maintainer
a distinct commit hash, preventing git from skipping pack transfer
- Make wait_for_event_on_relay poll in a retry loop so transient timing
gaps between DB write and query do not cause false negatives
Diffstat (limited to 'src/http/mod.rs')
| -rw-r--r-- | src/http/mod.rs | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/src/http/mod.rs b/src/http/mod.rs index ffb1562..cfd7c52 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs | |||
| @@ -26,8 +26,9 @@ use tokio::net::TcpListener; | |||
| 26 | use crate::config::Config; | 26 | use crate::config::Config; |
| 27 | use crate::git; | 27 | use crate::git; |
| 28 | use crate::metrics::Metrics; | 28 | use crate::metrics::Metrics; |
| 29 | use crate::nostr::builder::SharedDatabase; | 29 | use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase}; |
| 30 | use crate::purgatory::Purgatory; | 30 | use crate::purgatory::Purgatory; |
| 31 | use crate::sync::rejected_index::RejectedEventsIndex; | ||
| 31 | 32 | ||
| 32 | /// CORS headers required by GRASP-01 specification (lines 40-47) | 33 | /// CORS headers required by GRASP-01 specification (lines 40-47) |
| 33 | const CORS_ALLOW_ORIGIN: &str = "*"; | 34 | const CORS_ALLOW_ORIGIN: &str = "*"; |
| @@ -97,6 +98,10 @@ struct HttpService { | |||
| 97 | metrics: Option<Arc<Metrics>>, | 98 | metrics: Option<Arc<Metrics>>, |
| 98 | /// Purgatory for event/git coordination | 99 | /// Purgatory for event/git coordination |
| 99 | purgatory: Arc<Purgatory>, | 100 | purgatory: Arc<Purgatory>, |
| 101 | /// Write policy for re-processing hot-cache events after git push promotion | ||
| 102 | write_policy: Arc<Nip34WritePolicy>, | ||
| 103 | /// Rejected events index for hot-cache re-processing after git push promotion | ||
| 104 | rejected_events_index: Arc<RejectedEventsIndex>, | ||
| 100 | } | 105 | } |
| 101 | 106 | ||
| 102 | impl HttpService { | 107 | impl HttpService { |
| @@ -107,6 +112,8 @@ impl HttpService { | |||
| 107 | database: SharedDatabase, | 112 | database: SharedDatabase, |
| 108 | metrics: Option<Arc<Metrics>>, | 113 | metrics: Option<Arc<Metrics>>, |
| 109 | purgatory: Arc<Purgatory>, | 114 | purgatory: Arc<Purgatory>, |
| 115 | write_policy: Arc<Nip34WritePolicy>, | ||
| 116 | rejected_events_index: Arc<RejectedEventsIndex>, | ||
| 110 | ) -> Self { | 117 | ) -> Self { |
| 111 | Self { | 118 | Self { |
| 112 | relay, | 119 | relay, |
| @@ -115,6 +122,8 @@ impl HttpService { | |||
| 115 | database, | 122 | database, |
| 116 | metrics, | 123 | metrics, |
| 117 | purgatory, | 124 | purgatory, |
| 125 | write_policy, | ||
| 126 | rejected_events_index, | ||
| 118 | } | 127 | } |
| 119 | } | 128 | } |
| 120 | } | 129 | } |
| @@ -132,6 +141,8 @@ impl Service<Request<Incoming>> for HttpService { | |||
| 132 | let git_data_path = self.config.effective_git_data_path(); | 141 | let git_data_path = self.config.effective_git_data_path(); |
| 133 | let database = self.database.clone(); | 142 | let database = self.database.clone(); |
| 134 | let purgatory = self.purgatory.clone(); | 143 | let purgatory = self.purgatory.clone(); |
| 144 | let write_policy = self.write_policy.clone(); | ||
| 145 | let rejected_events_index = self.rejected_events_index.clone(); | ||
| 135 | 146 | ||
| 136 | // Handle OPTIONS preflight requests (CORS) | 147 | // Handle OPTIONS preflight requests (CORS) |
| 137 | // GRASP-01 spec line 47: Respond to OPTIONS with 204 No Content | 148 | // GRASP-01 spec line 47: Respond to OPTIONS with 204 No Content |
| @@ -293,6 +304,8 @@ impl Service<Request<Incoming>> for HttpService { | |||
| 293 | purgatory.clone(), | 304 | purgatory.clone(), |
| 294 | &git_data_path, | 305 | &git_data_path, |
| 295 | git_protocol.as_deref(), | 306 | git_protocol.as_deref(), |
| 307 | write_policy.clone(), | ||
| 308 | rejected_events_index.clone(), | ||
| 296 | ) | 309 | ) |
| 297 | .await; | 310 | .await; |
| 298 | 311 | ||
| @@ -557,12 +570,17 @@ fn derive_accept_key(request_key: &[u8]) -> String { | |||
| 557 | /// * `relay` - The LocalRelay for WebSocket connections | 570 | /// * `relay` - The LocalRelay for WebSocket connections |
| 558 | /// * `database` - The database for direct queries (e.g., push authorization) | 571 | /// * `database` - The database for direct queries (e.g., push authorization) |
| 559 | /// * `metrics` - Optional metrics for Prometheus endpoint | 572 | /// * `metrics` - Optional metrics for Prometheus endpoint |
| 573 | /// * `purgatory` - Purgatory for event/git coordination | ||
| 574 | /// * `write_policy` - Write policy for re-processing hot-cache events after git push promotion | ||
| 575 | /// * `rejected_events_index` - Rejected events index for hot-cache re-processing | ||
| 560 | pub async fn run_server( | 576 | pub async fn run_server( |
| 561 | config: Config, | 577 | config: Config, |
| 562 | relay: LocalRelay, | 578 | relay: LocalRelay, |
| 563 | database: SharedDatabase, | 579 | database: SharedDatabase, |
| 564 | metrics: Option<Arc<Metrics>>, | 580 | metrics: Option<Arc<Metrics>>, |
| 565 | purgatory: Arc<Purgatory>, | 581 | purgatory: Arc<Purgatory>, |
| 582 | write_policy: Arc<Nip34WritePolicy>, | ||
| 583 | rejected_events_index: Arc<RejectedEventsIndex>, | ||
| 566 | ) -> anyhow::Result<()> { | 584 | ) -> anyhow::Result<()> { |
| 567 | let bind_addr: SocketAddr = config.bind_address.parse()?; | 585 | let bind_addr: SocketAddr = config.bind_address.parse()?; |
| 568 | 586 | ||
| @@ -582,6 +600,8 @@ pub async fn run_server( | |||
| 582 | database.clone(), | 600 | database.clone(), |
| 583 | metrics.clone(), | 601 | metrics.clone(), |
| 584 | purgatory.clone(), | 602 | purgatory.clone(), |
| 603 | write_policy.clone(), | ||
| 604 | rejected_events_index.clone(), | ||
| 585 | ); | 605 | ); |
| 586 | 606 | ||
| 587 | tokio::spawn(async move { | 607 | tokio::spawn(async move { |