1

I have configured a webapi controller for masstransit . something like this .

_busControl = MassTransit.Bus.Factory.CreateUsingRabbitMq(x =>
            {
                x.Host(new Uri("rabbitmq://localhost/"), h =>{ });
            });
            _busControl.Start();

and the console application is my server which is listening to my commmands / events --

 var BusControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
             {
                 var host = cfg.Host(new Uri("rabbitmq://localhost/"), h =>
                {
                    //h.Username("guest");
                    //h.Password("guest");
                });

                 cfg.ReceiveEndpoint(host, "create_product_queue", config => config.Consumer<CreateInventoryProductItemHandler>());
                 cfg.ReceiveEndpoint(host, "ProductItemCreatedEvent", config => config.Handler<ProductItemCreatedEvent>(async context => await Console.Out.WriteLineAsync($"Product Item Id -----{context.Message.ProductItemId} "))); <---- this never gets executed . 
             });
            BusControl.Start();

And the controller action is something like -

[HttpPost("product")]
        public async Task<IActionResult> Post([FromBody] Product Product)
        {
            var endpoint = await Startup.Bus.GetSendEndpoint(new Uri("rabbitmq://localhost/create_product_queue"));
            await endpoint.Send<CreateInventoryProductItem>(new
            {
                ProductName = Product.ProductName,
                PartNumber = Product.PartNumber,
                ManufactureDate = Product.ManufacturedDate
            });
            return new HttpStatusCodeResult(StatusCodes.Status202Accepted);
        }

and the handler is --

public async Task Consume(ConsumeContext<CreateInventoryProductItem> context)
        {
            CreateInventoryProductItem Command = context.Message;
            Product Product = await Context.SaveAsync(new Product(Command.ProductName
                , Command.PartNumber
                , Command.ManufacturedDate));
            await context.Publish<ProductItemCreatedEvent>(Product.Id); <--- problem area

        }

Now my scenario is .

  1. Create a command object .

  2. Get the product Id from the Entity framework Context.SaveAsync() method which has been newly created.

  3. Publish the ProductId to the bus so that other listeners can listen to this product Id and act accordingly .

    I am trying to figure out the best pattern to be applied in this case .

Now the problem starts with -- await context.Publish<ProductItemCreatedEvent>(Product.Id); this line . It tries to publish again and again to the same queue infinitely . As a result same Product object is getting inserted hundreds of times ( pretty lame I know cause no unique constraint but thats not the question here ), and what happens is that my command handler inspite of being strongly typed its getting executed indefinitely . How to get rid of this situation . I am pretty new to masstransit concepts.

so can someone shed some light why is this happening .

Community
  • 1
  • 1
Joy
  • 6,438
  • 8
  • 44
  • 75

1 Answers1

1

So the problem is that you need to pass an object to the Publish overload that you are using:

await context.Publish<ProductItemCreatedEvent>(Product.Id);

If the ProductItemCreatedEvent included two properties, Id and Description, you would create an anonymous object to initialize the interface:

await context.Publish<ProductItemCreatedEvent>(new
{
    Id = Product.Id,
    Description = Product.Description,
});

This way, an object with properties is passed which can initiate the dynamically generated backing class for the event interface.

Chris Patterson
  • 28,659
  • 3
  • 47
  • 59