Confusion about a few things #1108
-
First, I want to say that Rebus is a hidden gem. I had been struggling with MassTransit for quite some time and I was ready to ditch it. I found Rebus mentioned on Reddit somewhere and I spent the last 1-2 days learning it. While I had some struggles getting it working, I think I'm finally there. At this point, I am confused about a couple of things and I wanted to ask some questions here. First let me explain my use case. I have a ASP.NET WebApi application (.NET 7) that is hosted in AWS using ECS. The purpose of this API is to perform some operations on S3 buckets. I have an endpoint to delete a folder in a particular S3 bucket, I also have an endpoint to copy files between two S3 buckets. I also have an endpoint to query the "status" of those copy & delete operations, so a very very small state machine is involved. The status of those delete operations are persisted in a DynamoDB table at the moment. Both of these operations can take some time, and it's important that each request to copy or delete is retained. I wanted to avoid a bunch of hand-spun logic to persist these operations, so that's where Rebus came in. Initially, I wanted to limit the infrastructure footprint of this so instead of hosting a separate, second service to handle copy & delete operations, I instead just kept that in a new Where I struggled first was documentation. There's a lot of it, but for some reason the getting started parts of the docs didn't help me at all. I use Microsoft's DI framework, but the getting started code samples didn't use any DI framework at all; it did it "manually" with a After a lot of googling, I found // In my composition root
services.AddRebus(RebusSetup.Setup);
// In a separate file...
public static class RebusSetup
{
public static RebusConfigurer Setup(RebusConfigurer config)
{
var sqsConfig = new AmazonSQSConfig
{
RegionEndpoint = RegionEndpoint.USEast1
};
const string queueName = "deployment-ops-queue";
return config
.Logging(x => x.Serilog())
.Transport(x => x.UseAmazonSQSAsOneWayClient(sqsConfig))
.Subscriptions(x => x.StoreInMemory())
.Routing(x => x.TypeBased()
.Map<DeleteDeploymentMessage>(queueName));
}
} The second point of confusion for me was how to set up a publisher and consumer in the same process. The best reference for this I found was this README. It seemed like I could register a single IBus for this (that both the API controller and BackgroundService used) or have the BackgroundService register its own IBus. I decided to go with the latter; although I'm not sure which one is better in this case. I assume if we ever want to rip out the BackgroundService into its own process, having two separate ServiceProviders and thus two IBus instances will help make this easier. The third point of confusion was the Which leads me to my fourth point of confusion, and probably the one I find most important. I assumed (because again, I didn't find docs that really walked me through what a transport means in a technical sense), that private static RebusConfigurer RebusSetup(RebusConfigurer config)
{
var sqsConfig = new AmazonSQSConfig
{
RegionEndpoint = RegionEndpoint.USEast1
};
const string queueName = "deployment-ops-queue";
return config
.Logging(x => x.Serilog())
.Transport(x => x.UseAmazonSQS(queueName, sqsConfig))
.Subscriptions(x => x.StoreInMemory())
.Routing(x => x.TypeBased()
.Map<DeleteDeploymentMessage>(queueName));
} Why is it that my queue name needs to be repeated for both the mappings and the In closing, I'll say that I might also have a fundamental misunderstanding of SQS itself. I'll admit that I've spent more time in the MassTransit and Rebus docs to learn about passing messages than I have in the AWS docs learning about how SQS works. My understanding is that SQS queues are just dumb pipes to send messages bi-directionally. And that they aren't tied to specific messages types or schemas. My plan was to use the same queue for both the Copy and Delete messages. My samples only show the delete message, but the copy message will be added later with a different message type. If I'm indeed misunderstanding fundamentals here, please let me know and I'd appreciate some pointers to learn what I'm missing. I apologize this ended up being a long post. I wanted to walk you through my journey and see if I can get some help on the pain points. Overall I found it really challenging to understand Rebus, but not as hard as it was to understand MT (which I never fully did, and ultimately gave up on it). Thank you! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
I dug into the I hope I have that right. Assuming I didn't miss it, it would be nice to have some basics like this covered in the getting started page somewhere, in the README as an intro / basic section, etc. |
Beta Was this translation helpful? Give feedback.
-
I believe this is the part you needed to pick up to understand how Rebus works 🙂 BUT there's one more thing: Viewing queues as BI-DIRECTIONAL pipes is wrong, because it implies that you would use it to perform "full duplex" operations (i.e. both for sending/receiving). It would be more accurate to think of a queue as a mailbox, which is where you put messages intended for ONE SPECIFIC RECIPIENT, which in turn implies that full duplex communication requires TWO queues: One for requests, and one for replies. E.g. if you have three different types of processors
which basically just illustrates the point that each thing capable of receiving messages must have its own "input queue" (i.e. the one whose name you specify when you configure the transport). And yes, it's perfectly OK to use one queue for multiple message types – the queue is for all work intended for one specific recipient. Btw regarding the documentation: Rebus has historically used the |
Beta Was this translation helpful? Give feedback.
I believe this is the part you needed to pick up to understand how Rebus works 🙂
BUT there's one more thing: Viewing queues as BI-DIRECTIONAL pipes is wrong, because it implies that y…