test(event-subscriber): the projection is sourced from register records (refs #153)
Ports, schema and failing tests for the subscriber half of S-19b-2, ahead of the implementation. The subscriber now listens on the `objecten` kanaal instead of `zaken`. An Objecten notification carries no record data — only the object URL — so the record is read back through the ACL (§8.1), and the zaak-shaped surface goes away: IsZaakCreated / IsZaakStatusSet / ZaakUrl / ZaakId and ToEntry's `Resource == "status"` mapping are replaced by IsRegisterRecordWritten + ObjectUrl. The notification log now holds the projected row itself (register id, status, reference), so a rebuild is a replay with no mapping rules and no upstream reads. The migration drops the old columns rather than renaming them — EF scaffolded renames that would have carried ZGW values into columns meaning something else — and empties both tables, since a pre-slice row is neither reprojectable nor re-derivable from the new source. Red: HandleAsync recognises a register write but does not yet read or project it, so the seven projection assertions fail on an empty store.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using EventSubscriber.Application;
|
||||
@@ -5,26 +6,28 @@ using EventSubscriber.Application;
|
||||
namespace EventSubscriber.Api;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP client to the ACL service. The subscriber enriches the projection with the zaak's reference
|
||||
/// (identificatie) by asking the ACL — the only code that may read ZGW (§8.1) — rather than reading
|
||||
/// OpenZaak itself (adr-proposal #78).
|
||||
/// HTTP client to the ACL service. An Objecten notification carries only the object URL, so the
|
||||
/// subscriber reads the register record back through the ACL — the only code that may talk to
|
||||
/// Objecten (§8.1, ADR-0028/ADR-0030) — rather than reading Objecten itself.
|
||||
/// </summary>
|
||||
public sealed class AclHttpClient(HttpClient http) : IAclClient
|
||||
{
|
||||
public async Task<string> GetZaakReferenceAsync(Uri zaakUrl, CancellationToken ct = default)
|
||||
public async Task<RegisterRecord?> GetRegisterRecordAsync(Uri objectUrl, CancellationToken ct = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(zaakUrl);
|
||||
ArgumentNullException.ThrowIfNull(objectUrl);
|
||||
|
||||
using var response = await http.PostAsJsonAsync(
|
||||
new Uri(http.BaseAddress!, "zaken/reference"), new ReferenceRequest(zaakUrl.ToString()), ct);
|
||||
response.EnsureSuccessStatusCode();
|
||||
new Uri(http.BaseAddress!, "register-records/read"),
|
||||
new ReadRequest(objectUrl.ToString()), ct);
|
||||
|
||||
var body = await response.Content.ReadFromJsonAsync<ReferenceResponse>(ct)
|
||||
?? throw new InvalidOperationException("The ACL returned an empty reference response.");
|
||||
return body.Reference;
|
||||
// The object holds no register record (deleted, or never one) — nothing to project (§8.6).
|
||||
if (response.StatusCode == HttpStatusCode.NotFound)
|
||||
return null;
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<RegisterRecord>(ct)
|
||||
?? throw new InvalidOperationException("The ACL returned an empty register record response.");
|
||||
}
|
||||
|
||||
private sealed record ReferenceRequest([property: JsonPropertyName("zaakUrl")] string ZaakUrl);
|
||||
|
||||
private sealed record ReferenceResponse([property: JsonPropertyName("reference")] string Reference);
|
||||
private sealed record ReadRequest([property: JsonPropertyName("objectUrl")] string ObjectUrl);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user