feat(openzaak): bounded retry + flagged write divergence (WP-60)
Local aanvraag/document writes and their paired ZGW writes aren't transactional; a ZGW failure after the local write succeeds used to diverge silently. ZgwHttpClient now retries transport-shaped failures (not 500, which can follow a partial commit on the non-idempotent statussen/rollen POSTs), and a ZGW failure that survives retry sets Aanvraag.ZgwError plus a zgw:divergence audit row instead of failing or diverging quietly. No outbox/reconcile job: three request-triggered write paths don't justify a persisted queue that would also need to carry citizen PII for the JWT audit claims. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Net;
|
||||
using BigRegister.Api.Data;
|
||||
using BigRegister.Api.Zgw;
|
||||
using BigRegister.Domain.Authorization;
|
||||
@@ -77,15 +78,38 @@ public class OpenZaakDocumentSourceTests
|
||||
Assert.Contains("\"vertrouwelijkheidaanduiding\":\"openbaar\"", body);
|
||||
}
|
||||
|
||||
// WP-60: once DocumentStore.Add has committed, a ZGW-side failure (config gap or transport)
|
||||
// no longer throws — the local document is authoritative and DrcUrl stays null (the same
|
||||
// detector LinkToZaak already skips on for pre-Zgw documents).
|
||||
|
||||
[Fact]
|
||||
public void Upload_throws_when_the_category_has_no_configured_informatieobjecttype()
|
||||
public void Upload_keeps_the_local_document_when_the_category_has_no_configured_informatieobjecttype()
|
||||
{
|
||||
var options = Options();
|
||||
var handler = new ZgwStubHandler(url => throw new InvalidOperationException($"no HTTP call expected, got {url}"));
|
||||
var source = new OpenZaakDocumentSource(new HttpClient(handler), new ZgwTokenProvider(options), options);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
source.Upload("local-1", "unknown-category", "registratie", "f.pdf", "application/pdf", [1, 2, 3], Caller));
|
||||
var response = source.Upload("local-1", "unknown-category", "registratie", "f.pdf", "application/pdf", [1, 2, 3], Caller);
|
||||
|
||||
Assert.Equal("local-1", response.LocalId);
|
||||
Assert.Empty(handler.Requests);
|
||||
Assert.Null(DocumentStore.Get(response.DocumentId)!.DrcUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Upload_keeps_the_local_document_and_does_not_throw_when_drc_rejects_it()
|
||||
{
|
||||
var options = Options();
|
||||
var handler = new ZgwStubHandler(
|
||||
url => throw new InvalidOperationException($"unexpected success body requested for {url}"),
|
||||
(_, _) => HttpStatusCode.BadRequest);
|
||||
var source = new OpenZaakDocumentSource(new HttpClient(handler), new ZgwTokenProvider(options), options);
|
||||
|
||||
var response = source.Upload("local-1", "identiteit", "registratie", "paspoort.pdf", "application/pdf",
|
||||
"%PDF-1.4 fake"u8.ToArray(), Caller);
|
||||
|
||||
Assert.Equal("local-1", response.LocalId);
|
||||
Assert.Null(DocumentStore.Get(response.DocumentId)!.DrcUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user