بنقرة واحدة
state-view-slice
Generate Marten read models, projections, and Wolverine HTTP GET endpoints for STATE_VIEW slices
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Generate Marten read models, projections, and Wolverine HTTP GET endpoints for STATE_VIEW slices
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | state-view-slice |
| description | Generate Marten read models, projections, and Wolverine HTTP GET endpoints for STATE_VIEW slices |
A STATE_VIEW slice projects event data into Marten read model documents. It generates:
IDocument) in <Context>/Slices/<SliceName>SingleStreamProjection or MultiStreamProjection) in Internal/<Context>/Slices/<SliceName>Note: STATE_VIEW slices do NOT contain commands or events. Events come from STATE_CHANGE slices.
Events (from STATE_CHANGE) → Marten Projection → ReadModel document → Wolverine GET endpoint
| Java / Axon | C# / Critter Stack |
|---|---|
@Entity JPA class | Marten document class |
JpaRepository | IQuerySession.LoadAsync<T>() |
@EventHandler Projector | Marten SingleStreamProjection<T> |
@QueryHandler | Direct query in GET endpoint |
QueryGateway.query() | IQuerySession.LoadAsync<T>() |
Flyway migration | Marten auto-creates schema |
ProjectionLifecycle.Async | ProjectionLifecycle.Async |
ProjectionLifecycle.Inline | ProjectionLifecycle.Inline |
Location: <Context>/Slices/<SliceName>/<SliceName>ReadModel.cs
using SlicingWorkshop.Common;
namespace SlicingWorkshop.<Context>.Slices.<SliceName>;
public class <SliceName>ReadModel : IReadModel
{
public Guid Id { get; set; }
public <Type> <FieldName> { get; set; }
// Add fields from readmodel definition
}
Location: <Context>/Slices/<SliceName>/Internal/<SliceName>Projection.cs
Single stream (one aggregate):
using Marten.Events.Aggregation;
using SlicingWorkshop.Events;
namespace SlicingWorkshop.<Context>.Slices.<SliceName>.Internal;
public class <SliceName>Projection : SingleStreamProjection<<SliceName>ReadModel>
{
public void Apply(<EventName> @event, <SliceName>ReadModel readModel)
{
readModel.Id = @event.AggregateId;
// Map event fields to read model fields
}
}
Multi-stream:
using Marten.Events.Aggregation;
using SlicingWorkshop.Events;
namespace SlicingWorkshop.<Context>.Slices.<SliceName>.Internal;
public class <SliceName>Projection : MultiStreamProjection<<SliceName>ReadModel, Guid>
{
public <SliceName>Projection()
{
Identity<<EventName>>(e => e.AggregateId);
}
public void Apply(<EventName> @event, <SliceName>ReadModel readModel)
{
readModel.Id = @event.AggregateId;
// Map fields
}
}
Add to the AddMarten options in Program.cs:
opts.Projections.Add<<SliceName>Projection>(ProjectionLifecycle.Async);
// or Inline for synchronous updates
Location: <Context>/Slices/<SliceName>/<SliceName>Endpoint.cs
using Marten;
using Wolverine.Http;
namespace SlicingWorkshop.<Context>.Slices.<SliceName>;
public static class <SliceName>Endpoint
{
[WolverineGet("/api/<context>/<resource>/{id}")]
public static async Task<<SliceName>ReadModel?> Get(
Guid id,
IQuerySession session)
{
return await session.LoadAsync<<SliceName>ReadModel>(id);
}
}
Location: <Context>/Slices/<SliceName>/Tests/<SliceName>ProjectionTests.cs
using Marten;
using SlicingWorkshop.Events;
using Xunit;
namespace SlicingWorkshop.<Context>.Slices.<SliceName>.Tests;
public class <SliceName>ProjectionTests : IClassFixture<AppFixture>
{
private readonly AppFixture _fixture;
public <SliceName>ProjectionTests(AppFixture fixture) => _fixture = fixture;
[Fact]
public async Task <SpecTitleAsPascalCase>()
{
var aggregateId = Guid.NewGuid();
// Apply events directly to the event store
using var session = _fixture.Store.LightweightSession();
session.Events.Append(aggregateId, new <EventName>(aggregateId /*, fields */));
await session.SaveChangesAsync();
// Wait for async projection (or use Inline)
await _fixture.Store.WaitForNonStaleProjectionDataAsync(TimeSpan.FromSeconds(5));
using var querySession = _fixture.Store.QuerySession();
var result = await querySession.LoadAsync<<SliceName>ReadModel>(aggregateId);
Assert.NotNull(result);
// Assert field values
}
}
| config.json Type | C# Type | Marten notes |
|---|---|---|
| UUID | Guid | Default Id type |
| String | string | |
| Date | DateOnly | |
| Integer | int | |
| Boolean | bool | |
| Decimal | decimal | |
| Multiple cardinality | List | Initialize in constructor |
| optional: true | T? |
ProjectionLifecycle.Inline for strongly consistent reads (same transaction)ProjectionLifecycle.Async for eventually consistent, high-throughput projectionsnull → Wolverine HTTP maps to 404 automaticallyGenerate event-driven automation processors for AUTOMATION slices using Wolverine message handlers
Transform slice definitions from config.json into C# code using Wolverine + Marten (Critter Stack)
Generate commands, events, aggregates, Wolverine HTTP endpoints (POST), and tests for STATE_CHANGE slices
Generate translators that map external events (from other bounded contexts or systems) into internal domain events using Wolverine handlers