Skip to content

Commit

Permalink
Merge pull request #126 from LeonAquitaine/master
Browse files Browse the repository at this point in the history
Added support for RabbitMQ, Docker-compose example
  • Loading branch information
lbotinelly authored Oct 12, 2023
2 parents f6c07ce + 3b856b7 commit 803fe8c
Show file tree
Hide file tree
Showing 18 changed files with 332 additions and 12 deletions.
11 changes: 11 additions & 0 deletions Samples/Sample05-Docker/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using MongoDB.Bson;
using Zen.Web.Host;

namespace Sample05_Docker
Expand All @@ -6,7 +7,17 @@ public class Program
{
public static void Main(string[] args)
{
Zen.MessageQueue.Queue.RegisterType("string");
Zen.MessageQueue.Queue.Send("string");
Zen.MessageQueue.Queue.Receive += (model) =>
{
Zen.Base.Log.Add(model.ToJson());
};


Builder.Start<Startup>(args);


}
}
}
2 changes: 2 additions & 0 deletions Samples/Sample05-Docker/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"ASPNETCORE_URLS": "https://+:443;http://+:80"
},
"publishAllPorts": true,
"httpPort": 80,
"sslPort": 443,
"useSSL": true
}
},
Expand Down
6 changes: 2 additions & 4 deletions Samples/Sample05-Docker/Sample05-Docker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@
<ItemGroup>
<ProjectReference Include="..\..\Zen.App\Zen.App.csproj" />
<ProjectReference Include="..\..\Zen.Base\Zen.Base.csproj" />
<ProjectReference Include="..\..\Zen.MessageQueue\Zen.MessageQueue.csproj" />
<ProjectReference Include="..\..\Zen.Module.Data.MongoDB\Zen.Module.Data.MongoDB.csproj" />
<ProjectReference Include="..\..\Zen.Module.MQ.RabbitMQ\Zen.Module.MQ.RabbitMQ.csproj" />
<ProjectReference Include="..\..\Zen.Web.App\Zen.Web.App.csproj" />
<ProjectReference Include="..\..\Zen.Web\Zen.Web.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>


</Project>
9 changes: 7 additions & 2 deletions Samples/Sample05-Docker/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@
"EnableHtml5": false
},
"Database": {
"MongoDB1": {
"ConnectionString": "mongodb://db-1:27017/zen-samples"
"MongoDB": {
"ConnectionString": "mongodb://db:27017/zen-samples"
}
},
"MessageQueue": {
"RabbitMQ": {
"HostName": "mq"
}
},
"AllowedHosts": "*"
Expand Down
27 changes: 27 additions & 0 deletions Zen.Base/Extension/Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,33 @@ public static T GetObject<T>(this IDictionary<string, object> dict, Dictionary<s
return (T) obj;
}

public static IEnumerable<Type> GetParentTypes(this Type type)
{
// https://stackoverflow.com/a/18375526/1845714

// is there any base type?
if (type == null)
{
yield break;
}

// return all implemented or inherited interfaces
foreach (var i in type.GetInterfaces())
{
yield return i;
}

// return all inherited types
var currentBaseType = type.BaseType;
while (currentBaseType != null)
{
yield return currentBaseType;
currentBaseType = currentBaseType.BaseType;
}
}



/// <summary>
/// Gets the method ext.
/// </summary>
Expand Down
1 change: 0 additions & 1 deletion Zen.Base/Module/Data/Adapter/DataAdapterPrimitive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq.Expressions;
using Zen.Base.Module.Data.Connection;
using Zen.Base.Module.Log;

namespace Zen.Base.Module.Data.Adapter
{
Expand Down
35 changes: 35 additions & 0 deletions Zen.MessageQueue/Configuration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.Extensions.Options;
using Zen.Base.Common;
using Zen.Base.Extension;
using Zen.Base.Module.Service;

namespace Zen.MessageQueue
{
public class Configuration : IConfigureOptions<Configuration.IOptions>
{
private readonly IOptions _options;

public Configuration(IOptions<Options> options) => _options = options.Value;

public void Configure(IOptions options)
{
_options.CopyMembersTo(options);
}

public interface IOptions
{
int HttpPort { get; set; }
int HttpsPort { get; set; }
}

[IoCIgnore]
public class Options : AutoOptions { }

[Priority(Level = -99)]
public class AutoOptions : IOptions // If nothing else is defined, AutoOptions kicks in.
{
public int HttpPort { get; set; } = 5000;
public int HttpsPort { get; set; } = 5001;
}
}
}
8 changes: 8 additions & 0 deletions Zen.MessageQueue/Current.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Zen.MessageQueue
{
public static class Current
{

public readonly static Configuration.IOptions Options = Base.Configuration.GetSettings<Configuration.IOptions, Configuration.Options>(new Configuration.Options(), "MessageQueue");
}
}
46 changes: 46 additions & 0 deletions Zen.MessageQueue/Queue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Zen.Base.Extension;
using Zen.Base.Module.Service;
using Zen.MessageQueue.Shared;

namespace Zen.MessageQueue
{

public delegate void MessageReceivedHandler(object item);

public static class Queue
{
private static readonly IMessageQueueBundle DefaultBundle = (IMessageQueueBundle)IoC.GetClassesByInterface<IMessageQueueBundle>(false)?.First()?.CreateInstance();

private static readonly Dictionary<Type, object> _cache = new Dictionary<Type, object>();

public static event MessageReceivedHandler Receive;


public static void RegisterType<T>(this T targetObject)
{

if (DefaultBundle == null)
throw new InvalidOperationException("No Message Queue adapter specificed. Try adding a Zen.Module.MQ.* reference.");

var type = typeof(T);

if (_cache.ContainsKey(type)) return;
MessageQueuePrimitive<T> adapter = DefaultBundle.AdapterType.CreateGenericInstance<T, MessageQueuePrimitive<T>>();

_cache[typeof(T)] = adapter;

adapter.Receive += (item) =>
{
Receive?.Invoke(item);
};
}

public static void Send<T>(this T targetObject)
{
((MessageQueuePrimitive<T>)_cache[typeof(T)]).Send(targetObject);
}
}
}
9 changes: 9 additions & 0 deletions Zen.MessageQueue/Shared/IMessageQueueBundle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Zen.MessageQueue.Shared
{
public interface IMessageQueueBundle
{
Type AdapterType { get; set; }
}
}
11 changes: 11 additions & 0 deletions Zen.MessageQueue/Shared/MessageQueuePrimitive.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Zen.MessageQueue.Shared
{
public delegate void MessageReceivedHandler<T>(T item);

public abstract class MessageQueuePrimitive<T>
{
public virtual void Send(T item) { }
public virtual event MessageReceivedHandler<T> Receive;

}
}
11 changes: 11 additions & 0 deletions Zen.MessageQueue/Zen.MessageQueue.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Zen.Base\Zen.Base.csproj" />
</ItemGroup>

</Project>
44 changes: 44 additions & 0 deletions Zen.Module.MQ.RabbitMQ/Configuration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Microsoft.Extensions.Options;
using Zen.Base.Common;
using Zen.Base.Module.Service;

namespace Zen.Module.MQ.RabbitMQ
{
public class Configuration : IConfigureOptions<Configuration.Options>
{
private readonly IOptions _options;

public Configuration(IOptions<Options> options) => _options = options.Value;

public void Configure(Options options)
{
options.HostName = _options.HostName;
}

public interface IOptions
{
string HostName { get; set; }
bool Durable { get; set; }
bool Exclusive { get; set; }
bool AutoDelete { get; set; }
}

[IoCIgnore]
public class Options : IOptions
{
public string HostName { get; set; }
public bool Durable { get; set; }
public bool Exclusive { get; set; }
public bool AutoDelete { get; set; }
}

[Priority(Level = -99)]
public class AutoOptions : IOptions // If nothing else is defined, AutoOptions kicks in.
{
public string HostName { get; set; } = @"localhost";
public bool Durable { get; set; } = true;
public bool Exclusive { get; set; } = false;
public bool AutoDelete { get; set; } = true;
}
}
}
56 changes: 56 additions & 0 deletions Zen.Module.MQ.RabbitMQ/RabbitMQAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using RabbitMQ.Client;
using Zen.Base;
using Zen.MessageQueue.Shared;
using Zen.Base.Extension;
using System.Text;
using RabbitMQ.Client.Events;
using System.Linq;
using System.Collections.Generic;

namespace Zen.Module.MQ.RabbitMQ
{
public class RabbitMQAdapter<T> : MessageQueuePrimitive<T>
{
private readonly Configuration.IOptions _options;
private readonly IModel _channel;
private readonly string _queueName;
private readonly List<string> _categories;

public RabbitMQAdapter()
{
_options = new Configuration.Options().GetSettings<Configuration.IOptions, Configuration.Options>("MessageQueue:RabbitMQ");

var factory = new ConnectionFactory { HostName = _options.HostName };
var connection = factory.CreateConnection();
_channel = connection.CreateModel();

_categories = typeof(T).GetParentTypes().Select(i => i.Name).ToList();
_queueName = typeof(T).FullName;


_channel.QueueDeclare(_queueName, durable: _options.Durable, exclusive: _options.Exclusive, autoDelete: _options.AutoDelete);

var consumer = new EventingBasicConsumer(_channel);

consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var item = Encoding.UTF8.GetString(body).FromJson<T>();

Receive?.Invoke(item);
};

_channel.BasicConsume(queue: _queueName, autoAck: true, consumer: consumer);
}

public override event MessageReceivedHandler<T> Receive;

public override void Send(T item)
{
var payload = item.ToJson();
var body = Encoding.UTF8.GetBytes(payload);

_channel.BasicPublish(exchange: string.Empty, routingKey: _queueName, basicProperties: null, body: body);
}
}
}
12 changes: 12 additions & 0 deletions Zen.Module.MQ.RabbitMQ/RabbitMQDefaultBundle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using Zen.Base.Common;
using Zen.MessageQueue.Shared;

namespace Zen.Module.MQ.RabbitMQ
{
[Priority(Level = -2)]
public class RabbitMQDefaultBundle : IMessageQueueBundle
{
public Type AdapterType { get; set; } = typeof(RabbitMQAdapter<>);
}
}
16 changes: 16 additions & 0 deletions Zen.Module.MQ.RabbitMQ/Zen.Module.MQ.RabbitMQ.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="RabbitMQ.Client" Version="6.5.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Zen.Base\Zen.Base.csproj" />
<ProjectReference Include="..\Zen.MessageQueue\Zen.MessageQueue.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit 803fe8c

Please sign in to comment.