fix(nats): delete+recreate stream when retention policy is incompatible
Some checks failed
lint / lint (push) Has been cancelled
test / unit (push) Has been cancelled
test / integration (push) Has been cancelled
lint / lint (pull_request) Has been cancelled
test / unit (pull_request) Has been cancelled
test / integration (pull_request) Has been cancelled

This commit is contained in:
2026-05-14 23:19:41 +02:00
parent 0caca58c1c
commit 40ed9b1ad8

View File

@@ -19,25 +19,28 @@ fn stream_config() -> StreamConfig {
} }
} }
/// Ensure the JetStream stream exists and has the current subject list. /// Ensure the JetStream stream exists with the current config.
/// Idempotent — creates if absent, updates subjects if already present. /// If an incompatible stream exists (e.g. wrong retention policy), deletes and recreates it.
pub async fn ensure_stream(client: &async_nats::Client) -> Result<(), DomainError> { pub async fn ensure_stream(client: &async_nats::Client) -> Result<(), DomainError> {
let js = jetstream::new(client.clone()); let js = jetstream::new(client.clone());
// Try to update first (covers the case where stream exists with stale subjects).
// Falls back to create if the stream doesn't exist yet. // Happy path: stream exists and config is compatible.
match js.update_stream(stream_config()).await { if js.update_stream(stream_config()).await.is_ok() {
Ok(_) => {
tracing::info!(subject = STREAM_SUBJECT, "JetStream stream updated"); tracing::info!(subject = STREAM_SUBJECT, "JetStream stream updated");
Ok(()) return Ok(());
} }
Err(e) => {
tracing::warn!("JetStream stream update failed ({e}), falling back to get_or_create"); // Update failed — retention policy mismatch or other incompatibility.
js.get_or_create_stream(stream_config()) // Delete the old stream and recreate with current config.
tracing::warn!(
"JetStream stream update failed (incompatible config), deleting '{STREAM_NAME}' and recreating"
);
let _ = js.delete_stream(STREAM_NAME).await;
js.create_stream(stream_config())
.await .await
.map(|_| ()) .map(|_| ())
.map_err(|e| DomainError::Internal(format!("JetStream stream setup failed: {e}"))) .map_err(|e| DomainError::Internal(format!("JetStream stream create failed: {e}")))
}
}
} }
// ── NatsTransport — JetStream publish ────────────────────────────────────── // ── NatsTransport — JetStream publish ──────────────────────────────────────