{"id":18872790,"url":"https://github.com/survivorbat/rabbitmq-miffy-wrapper","last_synced_at":"2025-04-14T16:17:14.292Z","repository":{"id":36306073,"uuid":"221700080","full_name":"survivorbat/rabbitmq-miffy-wrapper","owner":"survivorbat","description":"A wrapper framework designed to make working with an eventbus in C# easier, this library allows you to define event- and commandlistener with just two attributes and publish events without having to worry about low-level implementations","archived":true,"fork":false,"pushed_at":"2022-12-08T06:47:06.000Z","size":397,"stargazers_count":5,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-14T16:17:12.895Z","etag":null,"topics":["bus","bus-context","command-listener","csharp","csharp-library","dotnet","dotnet-core","dotnetcore","event-listener","eventbus","hostbuilder","listeners","microservice","microservice-architecture","microservices","miffy","miffy-framework","nuget","rabbitmq","wrapper-library"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/survivorbat.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-14T13:07:58.000Z","updated_at":"2025-04-12T21:57:45.000Z","dependencies_parsed_at":"2023-01-17T00:18:52.875Z","dependency_job_id":null,"html_url":"https://github.com/survivorbat/rabbitmq-miffy-wrapper","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/survivorbat%2Frabbitmq-miffy-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/survivorbat%2Frabbitmq-miffy-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/survivorbat%2Frabbitmq-miffy-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/survivorbat%2Frabbitmq-miffy-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/survivorbat","download_url":"https://codeload.github.com/survivorbat/rabbitmq-miffy-wrapper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248914117,"owners_count":21182359,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bus","bus-context","command-listener","csharp","csharp-library","dotnet","dotnet-core","dotnetcore","event-listener","eventbus","hostbuilder","listeners","microservice","microservice-architecture","microservices","miffy","miffy-framework","nuget","rabbitmq","wrapper-library"],"created_at":"2024-11-08T05:32:16.680Z","updated_at":"2025-04-14T16:17:14.271Z","avatar_url":"https://github.com/survivorbat.png","language":"C#","funding_links":["https://www.buymeacoffee.com/MaartenH"],"categories":[],"sub_categories":[],"readme":"# Miffy: RabbitMQ .NET Core Wrapper\n\n![GitHub](https://img.shields.io/github/license/survivorbat/rabbitmq-miffy-wrapper)\n![Nuget](https://img.shields.io/nuget/v/Miffy.Abstractions)\n\n**Important: This package has been moved from MaartenH.Minor.Miffy to just Miffy! If you're still using MaartenH.Minor.Miffy please consider moving.**\n\nThis is a wrapper library for the RabbitMQ Client in dotnetcore.\nThese packages allow you to easily set up event listeners and command listeners using RabbitMQ.\n\n**Miffy.Abstractions**\nContains all the interfaces and base classes of the framework.\nThis package also contains a testbus for in-memory queueing.\n\n![Nuget](https://img.shields.io/nuget/dt/Miffy.Abstractions)\n![Nuget](https://img.shields.io/nuget/dt/MaartenH.Minor.Miffy.Abstractions)\n\n**Miffy.MicroServices**\nThe package containing the classes used to set up a microservice host.\n\n![Nuget](https://img.shields.io/nuget/dt/Miffy.MicroServices)\n![Nuget](https://img.shields.io/nuget/dt/MaartenH.Minor.Miffy.MicroServices)\n\n**Miffy.RabbitMQBus**\nImplementation classes to use RabbitMQ with the framework\n\n![Nuget](https://img.shields.io/nuget/dt/Miffy.RabbitMQBus)\n![Nuget](https://img.shields.io/nuget/dt/MaartenH.Minor.Miffy.RabbitMQBus)\n\nThese packages can be found on nuget.org.\n\n## Example configuration\n\nTo allow you a quick start, here are a few examples on how to use this library.\n\n### Events\n\n#### Bus Context\nFirst, you need to open a connection using an implementation of the IBusContext\u003cIConnection\u003e class like so:\n```c#\nvar contextBuilder = new RabbitMqContextBuilder()\n                    .WithExchange(\"ExampleExchange\")\n                    .WithConnectionString(\"amqp://guest:guest@localhost\");\n\nusing IBusContext\u003cIConnection\u003e context = contextBuilder.CreateContext();\n```\n\nOr, if you wish, an in-memory context:\n```c#\nvar context = new TestBusContext();\n```\n\n#### Listening for events\n\nTo start listening for events you can either use a microservice host or implement your own listener.\nThis tutorial will only include the former option. You're going to need a DomainEvent class.\n\n```c#\npublic class ExampleEvent : DomainEvent\n{\n    public ExampleEvent() : base(\"ExampleTopic\") {}\n    public string ExampleData { get; set; }\n}\n```\n\nThen, you're going to need a callback function that handles such an event.\n\n```c#\npublic class ExampleEventListener\n{\n    [EventListener]\n    [Topic(\"ExampleTopic\")]\n    public void Handles(ExampleEvent exampleEvent)\n    {\n        DoSomethingWithData(exampleEvent.ExampleData);\n    }\n}\n```\n\nNow that we have that setup, we can register the event listener in our hostbuilder.\n\n```c#\n// Context builder code\n\nvar builder = new MicroserviceHostBuilder()\n\t\t\t\t.WithQueueName(\"MyService.Queue\")\n                .WithBusContext(context)\n                .AddEventListener\u003cExampleEventListener\u003e();\n\nusing var host = builder.CreateHost();\nhost.Start();\n\n// More code\n```\n\nAnd voila! Incoming events matching the topic will now be handled by the Handles method in the ExampleEventListener.\n\nYou can also allow reflection to take care of registering listeners, for example:\n```c#\nvar builder = new MicroserviceHostBuilder()\n\t\t\t\t.WithQueueName(\"MyService.Queue\")\n                .WithBusContext(context)\n                .UseConventions();\n```\n\nJust make sure an event listener has a EventListener attribute with one or more Topic attributes.\n\n#### Publishing events\n\nNow that we have a listener listening for events, we need something to publish events with. Luckily we have that too.\n\n```c#\n// Context builder code\n\npublic class ExampleEvent : DomainEvent\n{\n    public ExampleEvent() : base(\"ExampleTopic\") {}\n    public string ExampleData { get; set; }\n}\n\nvar exampleEvent = new ExampleEvent() { ExampleData = \"Hello World\" };\n\nvar publisher = new EventPublisher(context);\npublisher.PublishAsync(exampleEvent);\n```\n\nPublishers can be injected using the IEventPublisher interface and accept any event that inherits from DomainEvent.\n\nPlease note that DomainEvents can also contain a Process Id since v1.5.0 to follow a certain process through a system.\nThis property can be set using an overloaded constructor like so:\n\n```c#\npublic class ExampleEvent : DomainEvent\n{\n    public ExampleEvent(Guid processId) : base(\"Exampletopic\", processId) {}\n    public string ExampleData { get; set; }\n}\n\nGuid guid = /* Create a guid */;\nExampleEvent exampleEvent = new ExampleEvent(guid);\n```\n\n#### Listening for raw json data\n\nIn case you don't want to listen to specific events or want to\nserialize your own data. You can simply create an event listener with an input\ntype of _string_ like so:\n\n```c#\npublic class JsonEventListener\n{\n    [EventListener]\n    [Topic(\"ExampleTopic\")]\n    public void Handles(string rawJson)\n    {\n        DoSomethingWithJson(rawJson);\n    }\n}\n```\n\n#### Publishing raw json data\n\nIn case you want to publish raw json over the bus, you can use the overloaded variant of the Publish method like so:\n\n```c#\nvar publisher = new EventPublisher(context);\nstring body = \"{\\\"hello\\\": \\\"World\\\"}\";\npublisher.PublishAsync(timestamp: 500000, topic: \"TestTopic\", correlationId: Guid.NewGuid(), eventType: \"TestEvent\", body: body);\n```\n\n**Use this method with caution**, since deserializing raw or faulty data might throw errors and cause havoc.\n\n### Commands\n\nSending commands over the bus is also possible, first create a bus context from the **Events** section.\n\n#### Listening for commands\n\n```c#\nclass ExampleCommand : DomainCommand\n{\n    public ExampleCommand() : base(\"command.queue.somewhere\") {}\n    public string ExampleData { get; set; }\n}\n\nclass ExampleCommandResult {\n    public string ExampleData { get; set; }\n}\n```\n\n```c#\n// Note: The name of this queue corresponds to the DestinationQueue of the ExampleCommand\npublic class ExampleEventListener\n{\n    [CommandListener(\"command.queue.somewhere\")]\n    public ExampleCommandResult Handles(ExampleCommand command)\n    {\n        DoSomethingwithCommand(command);\n        return new ExampleCommandResult { ExampleData = \"Hello World\" };\n    }\n}\n```\n\nNow that we have that setup, we can register the command listener in our hostbuilder, the same way we register an event listener.\n\n```c#\n// Context builder code\n\nvar builder = new MicroserviceHostBuilder()\n                .WithBusContext(context)\n                .AddEventListener\u003cExampleCommandListener\u003e();\n\nusing var host = builder.CreateHost();\nhost.Start();\n\n// More code\n```\n\nAnd voila, now it's listening for incoming ExampleCommands and sends back data to the reply queue.\nPlease note that the Start() command is non-blocking, so in case you wish to\nkeep it running you'll need something to occupy the main thread.\n\nSince v1.6.0 it's also possible to .Pause() and .Resume() this host instance.\n\n#### Sending commands\n\nThe last piece of the puzzle is publishing commands. This can be done like so:\n\n```c#\n// Context builder code\n\npublic class ExampleCommand : DomainCommand\n{\n    public ExampleCommand() : base(\"command.queue.somewhere\") {}\n    public string ExampleData { get; set; }\n}\n\nvar exampleCommand = new ExampleCommand { ExampleData = \"Hello?\" };\n\nICommandPublisher publisher = new CommandPublisher(context)\nExampleCommandResult result = publisher.PublishAsync\u003cExampleCommandResult\u003e(exampleCommand).Result;\n\nAssert.AreEqual(\"Hello world!\", result.ExampleData);\n```\n\nPlease note that, just like events,  DomainCommands can also contain a Process Id since v1.5.0 to follow a certain process through a system.\nThis property can be set using an overloaded constructor like so:\n\n```c#\npublic class ExampleCommand : DomainCommand\n{\n    public ExampleCommand(Guid processId) : base(\"command.queue.somewhere\", processId) {}\n    public string ExampleData { get; set; }\n}\n\nGuid guid = /* Create a guid */;\nExampleCommand exampleCommand = new ExampleCommand(guid);\n```\n\nAnd that's about it! Have fun rabbiting :)\n\n## Invalid events\n\nAny incoming events or commands that can not be properly deserialized or other cause issues will be logged as critical.\nIn case you encounter such an error, please consider changing your listener's parameter to _string_ as described in the\n**Listening for raw json data** section of this README.\n\n## Library events\n\nThis library contains a few C# events (not to be confused with RabbitMQ events) that you can subscribe to.\nThese events are:\n\n### IMicroserviceHost\n- EventMessageReceived\n- EventMessageHandled\n- HostStarted\n- HostPaused\n- HostResumed\n\n## Notes\n- We encourage you to utilize a loggerfactory for logging, since bugs can easily be found by reading the logs.\n- Exceptions thrown in Command receivers **MUST** implement Serializable or have a _[Serializable]_ attribute\n- Events, exceptions and commands need to have the same classname in all involved services in order to be properly (de)serialized\n\n\u003ca href=\"https://www.buymeacoffee.com/MaartenH\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/default-red.png\" height=\"50\" widt=\"216\" alt=\"Buy Me A Coffee\" \u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurvivorbat%2Frabbitmq-miffy-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsurvivorbat%2Frabbitmq-miffy-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurvivorbat%2Frabbitmq-miffy-wrapper/lists"}