Completes the re-source (ADR-0030): the Event Subscriber's abonnement moves from `zaken` to `objecten`, in both the local stack's `nrc-subscribe` and the CI projection check. The OpenZaak → NRC check keeps its own `zaken` abonnement — OpenZaak still publishes, nothing in the product listens. - register-abonnement.py subscribes to `objecten`, and now treats the kanaal as part of "already current" — an abonnement left from before this slice points at the right callback but the wrong kanaal, and would never have been replaced on IP alone. - run-projection-check.sh opens its zaak *through the ACL* instead of straight against OpenZaak, because the ACL is what writes the register record the projection is now derived from. A zaak created behind the ACL's back produces no row — which is the re-source working. - The acceptance scenario is restated in register terms and gains the approval case: the same row moving INGEDIEND → INGESCHREVEN is now one registration's record being updated, not two unrelated ZGW events.
51 lines
2.0 KiB
C#
51 lines
2.0 KiB
C#
using EventSubscriber.Application;
|
|
|
|
namespace Acceptance.Support;
|
|
|
|
/// <summary>In-memory stand-ins for the Event Subscriber's projection store and notification
|
|
/// log, so the S-06 acceptance scenario runs without Postgres (real delivery is a live-stack
|
|
/// check). Mirrors the <c>InMemoryZaakGateway</c> approach used for the ACL scenario.</summary>
|
|
public sealed class InMemoryNotificationLog : INotificationLog
|
|
{
|
|
private readonly Dictionary<string, RecordedNotification> _byKey = [];
|
|
|
|
public Task<bool> TryRecordAsync(RecordedNotification notification, CancellationToken ct = default)
|
|
=> Task.FromResult(_byKey.TryAdd(notification.Key, notification));
|
|
|
|
public Task<IReadOnlyList<RecordedNotification>> AllAsync(CancellationToken ct = default)
|
|
=> Task.FromResult<IReadOnlyList<RecordedNotification>>([.. _byKey.Values]);
|
|
}
|
|
|
|
public sealed class InMemoryProjectionStore : IProjectionStore
|
|
{
|
|
private readonly Dictionary<string, RegisterEntry> _byId = [];
|
|
|
|
public Task UpsertAsync(RegisterEntry entry, CancellationToken ct = default)
|
|
{
|
|
_byId[entry.Id] = entry;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task ClearAsync(CancellationToken ct = default)
|
|
{
|
|
_byId.Clear();
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<IReadOnlyList<RegisterEntry>> AllAsync(CancellationToken ct = default)
|
|
=> Task.FromResult<IReadOnlyList<RegisterEntry>>([.. _byId.Values]);
|
|
|
|
public IReadOnlyList<RegisterEntry> RowsFor(string id)
|
|
=> [.. _byId.Values.Where(e => e.Id == id)];
|
|
}
|
|
|
|
/// <summary>An in-memory stand-in for the register the ACL reads back for the projector, so the
|
|
/// scenario runs without a running ACL or Objecten (S-19b-2, ADR-0030).</summary>
|
|
public sealed class InMemoryRegisterRecordClient : IAclClient
|
|
{
|
|
public Dictionary<string, RegisterRecord> Records { get; } = [];
|
|
|
|
public Task<RegisterRecord?> GetRegisterRecordAsync(Uri objectUrl, CancellationToken ct = default)
|
|
=> Task.FromResult(Records.TryGetValue(objectUrl.ToString(), out var record) ? record : null);
|
|
}
|