Skip to content
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
9 changes: 7 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
version: 2
updates:
- package-ecosystem: ""
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
interval: "weekly"

- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"
11 changes: 4 additions & 7 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@ on:
branches:
- dev
paths-ignore:
- 'docs/**/*'
- '**.md'
- '**.scss'
- '**.toml'
- '**.html'

jobs:
nuget:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- uses: actions/setup-dotnet@v1
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '7.0.x'
dotnet-version: '8.0.x'
dotnet-quality: 'preview'
- name: Create and push NuGet package
run: |
dotnet pack -c Debug -o nuget
Expand Down
11 changes: 4 additions & 7 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@ on:
tags:
- '*'
paths-ignore:
- 'docs/**/*'
- '**.md'
- '**.scss'
- '**.toml'
- '**.html'

jobs:
nuget:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- uses: actions/setup-dotnet@v1
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '7.0.x'
dotnet-version: '8.0.x'
dotnet-quality: 'preview'
- name: Create and push NuGet package
run: |
dotnet pack -c Release -o nuget -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
Expand Down
42 changes: 42 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: PR Build and test
on:
workflow_dispatch:
pull_request:

jobs:
test:
runs-on: ubuntu-latest
# env:
# TC_CLOUD_TOKEN: ${{ secrets.TC_TOKEN }}
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
dotnet-quality: 'preview'
-
name: Install dependencies
run: dotnet restore
-
name: Build
run: dotnet build --configuration Debug --no-restore
-
name: Prepare Testcontainers Cloud agent
if: env.TC_CLOUD_TOKEN != ''
uses: atomicjar/testcontainers-cloud-setup-action@main
-
name: Run tests
run: dotnet test --no-build
-
name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: |
test-results/**/*.xml
test-results/**/*.trx
test-results/**/*.json
2 changes: 1 addition & 1 deletion Eventuous.sln
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Eventuous.Tests.Kafka", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Eventuous.Gateway", "src\Gateway\src\Eventuous.Gateway\Eventuous.Gateway.csproj", "{E3D5B654-C68D-456B-8535-A9C38D37DFD2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Eventuous.Gateway.Tests", "src\Gateway\test\Eventuous.Gateway.Tests\Eventuous.Gateway.Tests.csproj", "{F89E7F27-D198-41DD-AC24-79709EF07537}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Eventuous.Tests.Gateway", "src\Gateway\test\Eventuous.Tests.Gateway\Eventuous.Tests.Gateway.csproj", "{F89E7F27-D198-41DD-AC24-79709EF07537}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B1AAD6CA-2710-41E0-9495-B43C313D6BCA}"
EndProject
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Eventuous</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Eventuous.Domain\Eventuous.Domain.csproj"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Eventuous.Shared\Eventuous.Shared.csproj" />
</ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion src/Core/src/Eventuous.Domain/Eventuous.Domain.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Eventuous</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Exceptions\ExceptionMessages.restext">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Eventuous</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Eventuous.Diagnostics\DiagnosticName.cs">
Expand Down
3 changes: 0 additions & 3 deletions src/Core/src/Eventuous.Producers/Eventuous.Producers.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Eventuous.Diagnostics\Eventuous.Diagnostics.csproj"/>
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Eventuous</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Eventuous.Shared\Eventuous.Shared.csproj"/>
Expand Down
1 change: 0 additions & 1 deletion src/Core/src/Eventuous.Shared/Eventuous.Shared.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Eventuous</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
Expand Down
12 changes: 9 additions & 3 deletions src/Core/src/Eventuous.Shared/TypeMap/TypeMapEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ namespace Eventuous;
class TypeMapEventSource : EventSource {
public static readonly TypeMapEventSource Log = new();

const int TypeNotMappedToNameId = 8;
const int TypeNameNotMappedToTypeId = 9;
const int TypeMapRegisteredId = 10;
const int TypeNotMappedToNameId = 8;
const int TypeNameNotMappedToTypeId = 9;
const int TypeMapRegisteredId = 10;
const int TypeMapAlreadyRegisteredId = 11;

[NonEvent]
public void TypeNotMappedToName(Type type)
Expand All @@ -31,4 +32,9 @@ public void TypeNameNotMappedToType(string typeName)
public void TypeMapRegistered(string type, string typeName) {
if (IsEnabled(EventLevel.Verbose, EventKeywords.All)) WriteEvent(TypeMapRegisteredId, type, typeName);
}

[Event(TypeMapAlreadyRegisteredId, Message = "Type already {0} registered as {1}", Level = EventLevel.Verbose)]
public void TypeAlreadyRegistered(string type, string typeName) {
if (IsEnabled(EventLevel.Warning, EventKeywords.All)) WriteEvent(TypeMapAlreadyRegisteredId, type, typeName);
}
}
30 changes: 24 additions & 6 deletions src/Core/src/Eventuous.Shared/TypeMap/TypeMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class TypeMapper {
public string GetTypeName<T>() {
if (!_map.TryGetValue(typeof(T), out var name)) {
Log.TypeNotMappedToName(typeof(T));

throw new UnregisteredTypeException(typeof(T));
}

Expand All @@ -54,13 +55,15 @@ public string GetTypeName(object o, bool fail = true) {
if (!fail) return "unknown";

Log.TypeNotMappedToName(o.GetType());

throw new UnregisteredTypeException(o.GetType());
}

[PublicAPI]
public string GetTypeNameByType(Type type) {
if (!_map.TryGetValue(type, out var name)) {
Log.TypeNotMappedToName(type);

throw new UnregisteredTypeException(type);
}

Expand All @@ -70,6 +73,7 @@ public string GetTypeNameByType(Type type) {
public Type GetType(string typeName) {
if (!_reverseMap.TryGetValue(typeName, out var type)) {
Log.TypeNameNotMappedToType(typeName);

throw new UnregisteredTypeException(typeName);
}

Expand All @@ -84,8 +88,19 @@ public void AddType<T>(string name)

readonly object _lock = new();

[PublicAPI]
public void AddType(Type type, string name) {
lock (_lock) {
if (_map.TryGetValue(type, out var registeredName)) {
if (registeredName != name) {
throw new ArgumentException($"Type {type.FullName} is already registered with a different name {registeredName}", nameof(name));
}

Log.TypeAlreadyRegistered(type.Name, name);

return;
}

_reverseMap[name] = type;
_map[type] = name;
}
Expand Down Expand Up @@ -129,15 +144,16 @@ IEnumerable<Assembly> Get(Assembly assembly) {
// ReSharper disable once ConvertClosureToMethodGroup
var referenced = assembly.GetReferencedAssemblies().Where(name => NamePredicate(name));
var assemblies = referenced.Select(Assembly.Load).ToList();

return assemblies.Concat(assemblies.SelectMany(Get)).Distinct();
}
}

bool NamePredicate(AssemblyName name)
=> name.Name != null &&
!name.Name.StartsWith("System.") &&
!name.Name.StartsWith("Microsoft.") &&
!name.Name.StartsWith("netstandard");
=> name.Name != null &&
!name.Name.StartsWith("System.") &&
!name.Name.StartsWith("Microsoft.") &&
!name.Name.StartsWith("netstandard");
}

static readonly Type AttributeType = typeof(EventTypeAttribute);
Expand Down Expand Up @@ -167,7 +183,9 @@ public class EventTypeAttribute(string eventType) : Attribute {

public class UnregisteredTypeException : Exception {
// ReSharper disable once SuggestBaseTypeForParameterInConstructor
public UnregisteredTypeException(Type type) : base($"Type {type.Name} is not registered in the type map") { }
public UnregisteredTypeException(Type type)
: base($"Type {type.Name} is not registered in the type map") { }

public UnregisteredTypeException(string type) : base($"Type name {type} is not registered in the type map") { }
public UnregisteredTypeException(string type)
: base($"Type name {type} is not registered in the type map") { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ public class NoOpCheckpointStore(ulong? start = null) : ICheckpointStore {
Checkpoint _start = new("", start);

public ValueTask<Checkpoint> GetLastCheckpoint(string checkpointId, CancellationToken cancellationToken) {
Logger.Current.CheckpointLoaded(this, _start);
var checkpoint = _start with { Id = checkpointId };
Logger.Current.CheckpointLoaded(this, checkpoint);

return new ValueTask<Checkpoint>(_start);
return new ValueTask<Checkpoint>(checkpoint);
}

public ValueTask<Checkpoint> StoreCheckpoint(Checkpoint checkpoint, bool force, CancellationToken cancellationToken) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,82 @@ namespace Eventuous.Subscriptions.Context;
/// Base interface for a consume context, which doesn't include the payload.
/// </summary>
public interface IBaseConsumeContext {
string MessageId { get; }
string MessageType { get; }
/// <summary>
/// Unique identifier of the message
/// </summary>
string MessageId { get; }
/// <summary>
/// Message type delivered in the message metadata or headers
/// </summary>
string MessageType { get; }
/// <summary>
/// Message content type, e.g. application/json
/// </summary>
string ContentType { get; }
/// <summary>
/// Stream name where message was read from. When reading from a category or $all, this will be the original stream name.
/// </summary>
StreamName Stream { get; }
/// <summary>
/// Event number in the original event stream
/// </summary>
ulong EventNumber { get; }
/// <summary>
/// Position of the received message in the subscription stream. It can differ from <see cref="EventNumber"/> when reading from a category or $all.
/// </summary>
ulong StreamPosition { get; }
/// <summary>
/// Message position in the global log
/// </summary>
ulong GlobalPosition { get; }
/// <summary>
/// System metadata value of the message produce date and time in UTC
/// </summary>
DateTime Created { get; }
/// <summary>
/// Metadata stored alongside the message
/// </summary>
Metadata? Metadata { get; }
/// <summary>
/// Baggage items for the consume context
/// </summary>
ContextItems Items { get; }
/// <summary>
/// Diagnostic activity parent context (can be remote context)
/// </summary>
ActivityContext? ParentContext { get; set; }
/// <summary>
/// Collection of message handling results, expected one result per handler
/// </summary>
HandlingResults HandlingResults { get; }
/// <summary>
/// Cancellation token passed from the subscription
/// </summary>
CancellationToken CancellationToken { get; set; }
/// <summary>
/// Message sequence number in the subscription (can be maintained locally, in process)
/// </summary>
ulong Sequence { get; }
/// <summary>
/// Subscription identifier, can also be used as a checkpoint
/// </summary>
string SubscriptionId { get; }
/// <summary>
/// Logging context for the consume pipeline
/// </summary>
LogContext LogContext { get; set; }
}

public interface IMessageConsumeContext : IBaseConsumeContext {
/// <summary>
/// Deserialized message payload
/// </summary>
object? Message { get; }
}

public interface IMessageConsumeContext<out T> : IBaseConsumeContext where T : class {
/// <summary>
/// Deserialized message payload
/// </summary>
T Message { get; }
}
Loading