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
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,37 @@ jobs:
run: dotnet restore
- name: Azure Tests
run: dotnet test ./tests/Paramore.Brighter.AzureServiceBus.Tests/Paramore.Brighter.AzureServiceBus.Tests.csproj --filter "Fragile!=CI" --configuration Release --logger "console;verbosity=normal" --blame -v n

# MongoDB tool too long time to run
# mongodb-ci:
# runs-on: ubuntu-latest
# timeout-minutes: 5
# needs: [build]
#
# services:
# mongo:
# image: mongo
# ports:
# - 27017:27017
# env:
# MONGO_INITDB_ROOT_USERNAME: root
# MONGO_INITDB_ROOT_PASSWORD: example
# MONGO_INITDB_DATABASE: brighter
# options: >-
# --health-cmd mongo
# --health-interval 20s
# --health-timeout 10s
# --health-retries 10
# steps:
# - uses: actions/checkout@v4
# - name: Setup dotnet
# uses: actions/setup-dotnet@v4
# with:
# dotnet-version: |
# 8.0.x
# 9.0.x
# - name: Install dependencies
# run: dotnet restore
# - name: MongoDB Tests
# run: dotnet test ./tests/Paramore.Brighter.MongoDb.Tests/Paramore.Brighter.MongoDb.Tests.csproj --filter "Fragile!=CI" --configuration Release --logger "console;verbosity=normal" --blame -v n

2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
9.0.x

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
71 changes: 71 additions & 0 deletions Brighter.sln
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Paramore.Brighter.MessageSc
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Paramore.Brighter.Hangfire.Tests", "tests\Paramore.Brighter.Hangfire.Tests\Paramore.Brighter.Hangfire.Tests.csproj", "{517D302F-46FC-4CDF-A190-D1E8A4F2E082}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Paramore.Brighter.Outbox.MongoDb", "src\Paramore.Brighter.Outbox.MongoDb\Paramore.Brighter.Outbox.MongoDb.csproj", "{4295A571-4653-43FD-971D-6C8F6E1B301B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Paramore.Brighter.Inbox.MongoDb", "src\Paramore.Brighter.Inbox.MongoDb\Paramore.Brighter.Inbox.MongoDb.csproj", "{34487FF5-FD63-4C64-9A33-9249B0C814AA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Paramore.Brighter.MongoDb", "src\Paramore.Brighter.MongoDb\Paramore.Brighter.MongoDb.csproj", "{9389F329-ED2B-45EB-B87F-E25304C82277}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Paramore.Brighter.Locking.MongoDb", "src\Paramore.Brighter.Locking.MongoDb\Paramore.Brighter.Locking.MongoDb.csproj", "{EE92EF65-BBA8-4601-A4F6-84A695548BD3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Paramore.Brighter.MongoDb.Tests", "tests\Paramore.Brighter.MongoDb.Tests\Paramore.Brighter.MongoDb.Tests.csproj", "{E988767C-A8F0-4EF1-B3CA-1822500F18DF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1981,6 +1991,66 @@ Global
{517D302F-46FC-4CDF-A190-D1E8A4F2E082}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{517D302F-46FC-4CDF-A190-D1E8A4F2E082}.Release|x86.ActiveCfg = Release|Any CPU
{517D302F-46FC-4CDF-A190-D1E8A4F2E082}.Release|x86.Build.0 = Release|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Debug|x86.ActiveCfg = Debug|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Debug|x86.Build.0 = Debug|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Release|Any CPU.Build.0 = Release|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Release|x86.ActiveCfg = Release|Any CPU
{4295A571-4653-43FD-971D-6C8F6E1B301B}.Release|x86.Build.0 = Release|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Debug|x86.ActiveCfg = Debug|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Debug|x86.Build.0 = Debug|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Release|Any CPU.Build.0 = Release|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Release|x86.ActiveCfg = Release|Any CPU
{34487FF5-FD63-4C64-9A33-9249B0C814AA}.Release|x86.Build.0 = Release|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Debug|x86.ActiveCfg = Debug|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Debug|x86.Build.0 = Debug|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Release|Any CPU.Build.0 = Release|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Release|x86.ActiveCfg = Release|Any CPU
{9389F329-ED2B-45EB-B87F-E25304C82277}.Release|x86.Build.0 = Release|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Debug|x86.ActiveCfg = Debug|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Debug|x86.Build.0 = Debug|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Release|Any CPU.Build.0 = Release|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Release|x86.ActiveCfg = Release|Any CPU
{EE92EF65-BBA8-4601-A4F6-84A695548BD3}.Release|x86.Build.0 = Release|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Debug|x86.ActiveCfg = Debug|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Debug|x86.Build.0 = Debug|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Release|Any CPU.Build.0 = Release|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Release|x86.ActiveCfg = Release|Any CPU
{E988767C-A8F0-4EF1-B3CA-1822500F18DF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -2078,6 +2148,7 @@ Global
{915BD9FD-2E29-4E2B-8DA3-A74055F32A20} = {C6B17EFD-4F05-4D45-AF3E-C4F3F790B994}
{7D8CE752-CCBB-4868-ADF0-30FF94CA611C} = {11935469-A062-4CFF-9F72-F4F41E14C2B4}
{FBAF452E-C0AB-4C4B-9A81-F1ED9616DE2A} = {202BA107-89D5-4868-AC5A-3527114C0109}
{E988767C-A8F0-4EF1-B3CA-1822500F18DF} = {329736D2-BF92-4D06-A7BF-19F4B6B64EDD}
{4469AEE3-B460-4948-A0A5-B9480EE70EA4} = {329736D2-BF92-4D06-A7BF-19F4B6B64EDD}
{8E414D7F-8DF0-4608-B47C-19213DB7E2B0} = {235DE1F1-E71B-4817-8E27-3B34FF006E4C}
{D5F5A100-F524-4020-B157-298EDC0910F4} = {8E414D7F-8DF0-4608-B47C-19213DB7E2B0}
Expand Down
5 changes: 4 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="9.2.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.2.0" />
<PackageVersion Include="MQTTnet" Version="5.0.1.1416" />
<PackageVersion Include="MySqlConnector" Version="2.4.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
Expand Down Expand Up @@ -128,11 +129,13 @@
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.2.efcore.9.0.0" />
<PackageVersion Include="Npgsql" Version="9.0.2" />
</ItemGroup>

<ItemGroup>
<GlobalPackageReference Include="MinVer" Version="6.0.0" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">

<ItemGroup Condition="'$(TargetFramework)' == 'net462' Or '$(TargetFramework)' == 'net472'">
<GlobalPackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
Expand Down
9 changes: 9 additions & 0 deletions docker-compose-mongodb.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
mongo:
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
MONGO_INITDB_DATABASE: brighter
ports:
- "27017:27017"
85 changes: 85 additions & 0 deletions src/Paramore.Brighter.Inbox.MongoDb/InboxMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System.Text.Json;
using MongoDB.Bson.Serialization.Attributes;
using Paramore.Brighter.MongoDb;

namespace Paramore.Brighter.Inbox.MongoDb;

/// <summary>
/// The MongoDb inbox message
/// </summary>
public class InboxMessage : IMongoDbCollectionTTL
{
/// <summary>
/// Initialize new instance of <see cref="InboxMessage"/>
/// </summary>
public InboxMessage()
{
}

/// <summary>
/// Initialize new instance of <see cref="InboxMessage"/>
/// </summary>
/// <param name="command">The command.</param>
/// <param name="id">The command id.</param>
/// <param name="contextKey">The context key.</param>
/// <param name="timeStamp">The time stamp of when the message was created.</param>
/// <param name="expireAfterSeconds">The expires after X seconds.</param>
public InboxMessage(object command, string id, string contextKey, DateTimeOffset timeStamp, long? expireAfterSeconds)
{
Id = new InboxMessageId { Id = id, ContextKey = contextKey };
TimeStamp = timeStamp;
CommandType = command.GetType().FullName!;
CommandBody = JsonSerializer.Serialize(command, JsonSerialisationOptions.Options);
ExpireAfterSeconds = expireAfterSeconds;
}

/// <summary>
/// The Message ID
/// </summary>
[BsonId]
public InboxMessageId Id { get; set; } = new();

/// <summary>
/// The <see cref="DateTimeOffset"/> when the message was crated
/// </summary>
public DateTimeOffset TimeStamp { get; set; }

/// <summary>
/// The command type(the full name)
/// </summary>
public string CommandType { get; set; } = string.Empty;

/// <summary>
/// The command body
/// </summary>
public string CommandBody { get; set; } = string.Empty;

/// <summary>
/// The TTL for this message
/// </summary>
public long? ExpireAfterSeconds { get; set; }

/// <summary>
/// The inbox message id
/// </summary>
public class InboxMessageId
{
/// <summary>
/// The id.
/// </summary>
public string Id { get; set; } = string.Empty;

/// <summary>
/// The context key.
/// </summary>
public string? ContextKey { get; set; }
}

/// <summary>
/// Convert the <see cref="CommandBody"/> to <typeparamref name="T"/>
/// </summary>
/// <typeparam name="T">The <see cref="IRequest"/>.</typeparam>
/// <returns>New instance of <typeparamref cref="T"/>.</returns>
public T ToCommand<T>()
=> JsonSerializer.Deserialize<T>(CommandBody, JsonSerialisationOptions.Options)!;
}
122 changes: 122 additions & 0 deletions src/Paramore.Brighter.Inbox.MongoDb/MongoDbInbox.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using MongoDB.Driver;
Comment thread
lillo42 marked this conversation as resolved.
Comment thread
lillo42 marked this conversation as resolved.
using Paramore.Brighter.Inbox.Exceptions;
using Paramore.Brighter.MongoDb;

namespace Paramore.Brighter.Inbox.MongoDb;

/// <summary>
/// The inbox implementation to MongoDB
/// </summary>
public class MongoDbInbox : BaseMongoDb<InboxMessage>, IAmAnInboxAsync, IAmAnInboxSync
{
/// <summary>
/// Initialize a new instance of <see cref="MongoDbInbox"/>.
/// </summary>
/// <param name="configuration">The configuration.</param>
public MongoDbInbox(MongoDbConfiguration configuration)
: base(configuration)
{
}

/// <inheritdoc />
public bool ContinueOnCapturedContext { get; set; }

/// <inheritdoc />
public async Task AddAsync<T>(T command, string contextKey, int timeoutInMilliseconds = -1,
CancellationToken cancellationToken = default) where T : class, IRequest
{
var message = new InboxMessage(command, command.Id, contextKey, Configuration.TimeProvider.GetUtcNow(),
ExpireAfterSeconds);

try
{
await Collection.InsertOneAsync(message, cancellationToken: cancellationToken)
.ConfigureAwait(ContinueOnCapturedContext);
}
catch (MongoWriteException e)
{
if (e.WriteError.Category == ServerErrorCategory.DuplicateKey)
{
return;
}

throw;
}
}
Comment thread
lillo42 marked this conversation as resolved.


/// <inheritdoc />
public async Task<T> GetAsync<T>(string id, string contextKey, int timeoutInMilliseconds = -1,
CancellationToken cancellationToken = default) where T : class, IRequest
{
var commandId = new InboxMessage.InboxMessageId { Id = id, ContextKey = contextKey };
var filter = Builders<InboxMessage>.Filter.Eq(x => x.Id, commandId);

var command = await Collection.Find(filter)
.FirstOrDefaultAsync(cancellationToken)
.ConfigureAwait(ContinueOnCapturedContext);

if (command == null)
{
throw new RequestNotFoundException<T>(id);
}

return command.ToCommand<T>();
}

/// <inheritdoc />
public async Task<bool> ExistsAsync<T>(string id, string contextKey, int timeoutInMilliseconds = -1,
CancellationToken cancellationToken = default) where T : class, IRequest
{
var commandId = new InboxMessage.InboxMessageId { Id = id, ContextKey = contextKey };
var filter = Builders<InboxMessage>.Filter.Eq("Id", commandId);
return await Collection.Find(filter)
.AnyAsync(cancellationToken: cancellationToken)
.ConfigureAwait(ContinueOnCapturedContext);
}

/// <inheritdoc />
public void Add<T>(T command, string contextKey, int timeoutInMilliseconds = -1) where T : class, IRequest
{
var message = new InboxMessage(command, command.Id, contextKey, Configuration.TimeProvider.GetUtcNow(),
ExpireAfterSeconds);

try
{
Collection.InsertOne(message);
}
catch (MongoWriteException e)
{
if (e.WriteError.Category == ServerErrorCategory.DuplicateKey)
{
return;
}

throw;
}
}

/// <inheritdoc />
public T Get<T>(string id, string contextKey, int timeoutInMilliseconds = -1) where T : class, IRequest
{
var commandId = new InboxMessage.InboxMessageId { Id = id, ContextKey = contextKey };
var filter = Builders<InboxMessage>.Filter.Eq(x => x.Id, commandId);

var command = Collection.Find(filter).FirstOrDefault();
if (command == null)
{
throw new RequestNotFoundException<T>(id);
}

return command.ToCommand<T>();
}

/// <inheritdoc />
public bool Exists<T>(string id, string contextKey, int timeoutInMilliseconds = -1) where T : class, IRequest
{
var commandId = new InboxMessage.InboxMessageId { Id = id, ContextKey = contextKey };
var filter = Builders<InboxMessage>.Filter.Eq("Id", commandId);
return Collection.Find(filter)
.Any();
}
}
Loading