Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor code to remove unnecessary using directives and clean up project file formatting #564

Merged
merged 4 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
branches: [ main ]
paths:
- "src/**"
- "test/**"
- "tests/**"
- "samples/**"
concurrency:
group: CosmosDbConnect
Expand Down
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,32 @@ Sekiban - Event Sourcing and CQRS Framework using C#. It can store data into Azu

## (NEW) Sekiban new version - Sekiban.Pure.Orleans

**We are in development for new version of Sekiban.** It is more functional and work with Microsoft Orleans as well. You can see new sekiban information on [README_Pure.md](./README_Pure.md) for quick instruction for LLM, look at [README_Pure_For_LLM.md](./README_Pure_For_LLM.md).
We moved main repository for the new Sekiban.Pure.Orleans project. Past project Sekiban.Core and upto 0.23 version to core_main branch of this repository.

[Sekiban core_main branch](https://github.com/J-Tech-Japan/Sekiban/tree/core_main)

mainレポジトリは、新しく開発中の Sekiban.Pure.Orleansプロジェクトのみを残したものとなっています。旧バージョンは、core_mainブランチに残しています。
[Sekiban core_main branch](https://github.com/J-Tech-Japan/Sekiban/tree/core_main)

新しいOrleans 対応Sekibanに関しては[README_Pure_JP.md](./README_Pure_JP.md)をご覧ください。


## What is Sekiban?

**Sekiban** is an application development framework that leverages **Event Sourcing and CQRS** principles. Built with C#
and .NET Core 8+, it allows developers to use a declarative API to create event sourcing applications. Sekiban supports
and .NET Core 9+, it allows developers to use a declarative API to create event sourcing applications. **New Version* of Sekiban is now working with [Microsoft Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/overview) and use of actor model increace its scalability and performance in multi thread environment. Sekiban supports
various event stores such as [Microsoft Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db)
, [Amazon Dynamo DB](https://aws.amazon.com/dynamodb/) and Postgres, facilitating deployment on either Azure or AWS.
, and Postgres, facilitating deployment on either Azure or AWS.

## Getting started


Do you want to start coding? If so, please see [Quick Start](https://github.com/J-Tech-Japan/Sekiban/blob/main/docs/docfx_project/articles/quick-start.md)
Do you want to start coding? If so, please see [Readme Pure](https://github.com/J-Tech-Japan/Sekiban/blob/main/README_Pure.md)

日本語の情報をお探しでしょうか? [Sekiban の紹介](https://github.com/J-Tech-Japan/Sekiban/blob/main/README_Pure_JP.md) のページから幾らかの記事が日本語で書かれています。開発者は日本語も分かりますので日本語の情報も増やしていきたいと思っています。

## AI Programming?

日本語の情報をお探しでしょうか? [Sekiban - イベントソーシングとCQRSフレームワークの紹介](https://github.com/J-Tech-Japan/Sekiban/blob/main/docs/docfx_project/articles_ja/intro.md) のページから幾らかの記事が日本語で書かれています。開発者は日本語も分かりますので日本語の情報も増やしていきたいと思っています。
You might use coding agent like Devin, Cline or Cursor .. etc. We made [Readme for LLM](https://github.com/J-Tech-Japan/Sekiban/blob/main/README_Pure_For_LLM.md) so you can copy and paste for framework instructions.

## Sponsors

Expand All @@ -46,7 +54,7 @@ Sekiban is an Apache 2.0 open source project with its ongoing development. We wi

If you've landed here, you're likely already familiar with Event Sourcing and CQRS. However, if you require more
detailed insights, Greg Young's informative YouTube talk might be of assistance. Check out
the [transcript](https://www.eventstore.com/blog/transcript-of-greg-youngs-talk-at-code-on-the-beach-2014-cqrs-and-event-sourcing)
the [transcript](https://www.kurrent.io/blog/transcript-of-greg-youngs-talk-at-code-on-the-beach-2014-cqrs-and-event-sourcing)
of Greg's presentation at the Code on the Beach 2014 event on CQRS and Event Sourcing.
Greg suggests creating your event sourcing system instead of relying on frameworks, a viewpoint I share, as constructing
your framework can deepen your understanding of event sourcing concepts.
Expand Down Expand Up @@ -84,7 +92,7 @@ projections, tests, and queries for practical solutions without unnecessary comp

## Compatibility

Sekiban is compatible with .NET 8 and 9.
Sekiban Pure is compatible with .NET 9.

For **Azure Cosmos DB**, Sekiban supports
the [Hierarchical Partition Key](https://learn.microsoft.com/en-us/azure/cosmos-db/hierarchical-partition-keys?tabs=net-v3%2Cbicep)
Expand All @@ -95,7 +103,7 @@ When using **Dynamo DB** with Sekiban, you need to set up a Partition Key and So

## Scale of Sekiban Projects

As of Sekiban version 0.15.x, the framework doesn't have built-in materialized view helper features. Sekiban's Live
As of Sekiban version 1.0.0.Preview, we are working on built-in materialized view helper features. Sekiban's Live
Projection capability is well-suited for small to medium-sized systems. Typically, Sekiban can handle Live Projections
provided the system memory can accommodate the size of the Multiple Projections.

Expand Down
4 changes: 2 additions & 2 deletions internalUsages/MemStat.Net.Web/MemStat.Net.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2"/>
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.1"/>
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/Branch.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using Sekiban.Pure.Aggregates;
namespace Pure.Domain;

Expand Down
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/BranchCreated.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using Sekiban.Pure.Events;
namespace Pure.Domain;

Expand Down
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/BranchNameChanged.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using Sekiban.Pure.Events;
namespace Pure.Domain;

Expand Down
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/ChangeBranchName.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using ResultBoxes;
using Sekiban.Pure.Aggregates;
using Sekiban.Pure.Command.Executor;
Expand Down
8 changes: 3 additions & 5 deletions internalUsages/Pure.Domain/ChangeClientName.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using ResultBoxes;
using Sekiban.Pure.Aggregates;
using Sekiban.Pure.Command.Executor;
Expand All @@ -8,14 +7,13 @@
namespace Pure.Domain;

[GenerateSerializer]
public record ChangeClientName(Guid ClientId, string Name)
: ICommandWithHandler<ChangeClientName, ClientProjector>
public record ChangeClientName(Guid ClientId, string Name) : ICommandWithHandler<ChangeClientName, ClientProjector>
{
public int? ReferenceVersion { get; init; }

public PartitionKeys SpecifyPartitionKeys(ChangeClientName command) =>
PartitionKeys<ClientProjector>.Existing(ClientId);

public ResultBox<EventOrNone> Handle(ChangeClientName command, ICommandContext<IAggregatePayload> context) =>
EventOrNone.Event(new ClientNameChanged(command.Name));
}
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/Client.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using Sekiban.Pure.Aggregates;
namespace Pure.Domain;

Expand Down
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/ClientCreated.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using Sekiban.Pure.Events;
namespace Pure.Domain;

Expand Down
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/ClientNameChanged.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using Sekiban.Pure.Events;
namespace Pure.Domain;

Expand Down
6 changes: 2 additions & 4 deletions internalUsages/Pure.Domain/ClientProjector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ public class ClientProjector : IAggregateProjector
public IAggregatePayload Project(IAggregatePayload payload, IEvent ev) =>
(payload, ev.GetPayload()) switch
{
(EmptyAggregatePayload, ClientCreated created) =>
new Client(created.BranchId, created.Name, created.Email),
(Client client, ClientNameChanged changed) =>
client with { Name = changed.Name },
(EmptyAggregatePayload, ClientCreated created) => new Client(created.BranchId, created.Name, created.Email),
(Client client, ClientNameChanged changed) => client with { Name = changed.Name },
_ => payload
};
}
7 changes: 3 additions & 4 deletions internalUsages/Pure.Domain/CreateClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using ResultBoxes;
using Sekiban.Pure.Aggregates;
using Sekiban.Pure.Command.Executor;
Expand All @@ -8,12 +7,12 @@
namespace Pure.Domain;

[GenerateSerializer]
public record CreateClient(Guid BranchId, string Name, string Email)
public record CreateClient(Guid BranchId, string Name, string Email)
: ICommandWithHandler<CreateClient, ClientProjector>
{
public PartitionKeys SpecifyPartitionKeys(CreateClient command) =>
public PartitionKeys SpecifyPartitionKeys(CreateClient command) =>
PartitionKeys<ClientProjector>.Generate();

public ResultBox<EventOrNone> Handle(CreateClient command, ICommandContext<IAggregatePayload> context) =>
EventOrNone.Event(new ClientCreated(command.BranchId, command.Name, command.Email));
}
4 changes: 2 additions & 2 deletions internalUsages/Pure.Domain/Pure.Domain.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
<ProjectReference Include="..\..\src\Sekiban.Pure.Orleans\Sekiban.Pure.Orleans.csproj" />
<PackageReference Include="Microsoft.Orleans.Server" Version="9.1.2" />
<ProjectReference Include="..\..\src\Sekiban.Pure.Orleans\Sekiban.Pure.Orleans.csproj"/>
<PackageReference Include="Microsoft.Orleans.Server" Version="9.1.2"/>
</ItemGroup>

</Project>
40 changes: 20 additions & 20 deletions internalUsages/Pure.Domain/PureDomainEventsJsonContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ namespace Pure.Domain;
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(EventDocumentCommon))]
[JsonSerializable(typeof(EventDocumentCommon[]))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.BranchCreated>))]
[JsonSerializable(typeof(Pure.Domain.BranchCreated))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.BranchNameChanged>))]
[JsonSerializable(typeof(Pure.Domain.BranchNameChanged))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.ClientCreated>))]
[JsonSerializable(typeof(Pure.Domain.ClientCreated))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.ClientNameChanged>))]
[JsonSerializable(typeof(Pure.Domain.ClientNameChanged))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.PaymentProcessedShoppingCart>))]
[JsonSerializable(typeof(Pure.Domain.PaymentProcessedShoppingCart))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.ShoppingCartCreated>))]
[JsonSerializable(typeof(Pure.Domain.ShoppingCartCreated))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.ShoppingCartItemAdded>))]
[JsonSerializable(typeof(Pure.Domain.ShoppingCartItemAdded))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.UserConfirmed>))]
[JsonSerializable(typeof(Pure.Domain.UserConfirmed))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.UserRegistered>))]
[JsonSerializable(typeof(Pure.Domain.UserRegistered))]
[JsonSerializable(typeof(EventDocument<Pure.Domain.UserUnconfirmed>))]
[JsonSerializable(typeof(Pure.Domain.UserUnconfirmed))]
[JsonSerializable(typeof(EventDocument<BranchCreated>))]
[JsonSerializable(typeof(BranchCreated))]
[JsonSerializable(typeof(EventDocument<BranchNameChanged>))]
[JsonSerializable(typeof(BranchNameChanged))]
[JsonSerializable(typeof(EventDocument<ClientCreated>))]
[JsonSerializable(typeof(ClientCreated))]
[JsonSerializable(typeof(EventDocument<ClientNameChanged>))]
[JsonSerializable(typeof(ClientNameChanged))]
[JsonSerializable(typeof(EventDocument<PaymentProcessedShoppingCart>))]
[JsonSerializable(typeof(PaymentProcessedShoppingCart))]
[JsonSerializable(typeof(EventDocument<ShoppingCartCreated>))]
[JsonSerializable(typeof(ShoppingCartCreated))]
[JsonSerializable(typeof(EventDocument<ShoppingCartItemAdded>))]
[JsonSerializable(typeof(ShoppingCartItemAdded))]
[JsonSerializable(typeof(EventDocument<UserConfirmed>))]
[JsonSerializable(typeof(UserConfirmed))]
[JsonSerializable(typeof(EventDocument<UserRegistered>))]
[JsonSerializable(typeof(UserRegistered))]
[JsonSerializable(typeof(EventDocument<UserUnconfirmed>))]
[JsonSerializable(typeof(UserUnconfirmed))]
public partial class PureDomainEventsJsonContext : JsonSerializerContext
{
}
1 change: 0 additions & 1 deletion internalUsages/Pure.Domain/RegisterBranch.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Orleans;
using ResultBoxes;
using Sekiban.Pure.Aggregates;
using Sekiban.Pure.Command.Executor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ public static ResultBox<bool> HandleQuery(
UserExistsQueryFromMultiProjection query,
IQueryContext context) =>
projection.Payload.Users.Values.Any(user => user.Email == query.Email);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ public static ResultBox<IEnumerable<string>> HandleSort(
IEnumerable<string> filteredList,
UserQueryFromAggregateProjection query,
IQueryContext context) => filteredList.OrderBy(name => name).ToList();
}
}
1 change: 0 additions & 1 deletion tests/MemStat.Net.Test/MemoryUsageSpecs.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection;

namespace MemStat.Net.Test;

public class MemoryUsageSpecs
Expand Down
5 changes: 2 additions & 3 deletions tests/Pure.Domain.Test/BasicTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Pure.Domain.Generated;
using Sekiban.Pure.Projectors;
using Sekiban.Pure.Documents;
using Sekiban.Pure.Projectors;
namespace Pure.Domain.Test;

public class BasicTests
Expand All @@ -25,7 +24,7 @@ public void TenantPartitionKeysTest()
Assert.Equal("tenant1", partitionKeys.RootPartitionKey);
Assert.Equal("group1", partitionKeys.Group);
}

public string GetVersion<TAggregateProjector>() where TAggregateProjector : IAggregateProjector, new() =>
new TAggregateProjector().GetVersion();
}
6 changes: 4 additions & 2 deletions tests/Pure.Domain.Test/BranchManagementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public class BranchManagementTests
[Fact]
public async Task ChangeBranchNameSpec()
{
var executor = new CommandExecutor(new ServiceCollection().BuildServiceProvider()) { EventTypes = new PureDomainEventTypes() };
var executor = new CommandExecutor(new ServiceCollection().BuildServiceProvider())
{ EventTypes = new PureDomainEventTypes() };

Assert.Empty(executor.Repository.Events);
var executed = await executor.Execute(new RegisterBranch("branch1"), CommandMetadata.Create("test"));
Expand All @@ -37,7 +38,8 @@ public async Task ChangeBranchNameSpec()
[Fact]
public async Task MultipleBranchesSpec()
{
var executor = new CommandExecutor(new ServiceCollection().BuildServiceProvider()) { EventTypes = new PureDomainEventTypes() };
var executor = new CommandExecutor(new ServiceCollection().BuildServiceProvider())
{ EventTypes = new PureDomainEventTypes() };

Assert.Empty(executor.Repository.Events);
var executed = await executor.Execute(new RegisterBranch("branch 0"), CommandMetadata.Create("test"));
Expand Down
36 changes: 17 additions & 19 deletions tests/Pure.Domain.Test/EventRemovalTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using Pure.Domain;
using Pure.Domain.Generated;
using Sekiban.Pure.Command.Handlers;
using Sekiban.Pure.Events;
using Sekiban.Pure.Executors;
using Sekiban.Pure.Repositories;

namespace Pure.Domain.Test;

public class EventRemovalTests
Expand All @@ -20,42 +18,42 @@ public async Task RemoveAllEvents_ShouldClearAllEventsFromRepository()
new FunctionCommandMetadataProvider(() => "test"),
repository,
new ServiceCollection().BuildServiceProvider());

// Add some events to the repository
await executor.CommandAsync(new RegisterBranch("branch1"));
await executor.CommandAsync(new RegisterUser("user1", "user1@example.com"));

// Verify that events were added
Assert.NotEmpty(executor.Repository.Events);
Assert.Equal(2, executor.Repository.Events.Count);

// Create an InMemoryEventWriter with the repository
var eventWriter = new InMemoryEventWriter(repository);

// Act
await eventWriter.RemoveAllEvents();

// Assert
Assert.Empty(executor.Repository.Events);
}

[Fact]
public async Task RemoveAllEvents_ShouldWorkWithEmptyRepository()
{
// Arrange
var repository = new Repository();
var eventWriter = new InMemoryEventWriter(repository);

// Verify that repository is empty
Assert.Empty(repository.Events);

// Act
await eventWriter.RemoveAllEvents();

// Assert
Assert.Empty(repository.Events);
}

[Fact]
public async Task RemoveAllEvents_ShouldAllowAddingEventsAfterRemoval()
{
Expand All @@ -66,26 +64,26 @@ public async Task RemoveAllEvents_ShouldAllowAddingEventsAfterRemoval()
new FunctionCommandMetadataProvider(() => "test"),
repository,
new ServiceCollection().BuildServiceProvider());

// Add some events to the repository
await executor.CommandAsync(new RegisterBranch("branch1"));

// Verify that events were added
Assert.NotEmpty(executor.Repository.Events);
Assert.Single(executor.Repository.Events);

// Create an InMemoryEventWriter with the repository
var eventWriter = new InMemoryEventWriter(repository);

// Act
await eventWriter.RemoveAllEvents();

// Assert that events were removed
Assert.Empty(executor.Repository.Events);

// Add new events after removal
await executor.CommandAsync(new RegisterUser("user1", "user1@example.com"));

// Assert that new events were added
Assert.NotEmpty(executor.Repository.Events);
Assert.Single(executor.Repository.Events);
Expand Down
Loading
Loading