public static void UseMessageQueue(this Configuration config, string tablename = "messages") { config.GetOrAddTable(new QueueTable(tablename)); config.Decorate <Func <DocumentTransaction, DmlCommand, Func <object> > >((_, decoratee) => (tx, command) => () => Switch <object> .On(command) .Match <EnqueueCommand>(enqueueCommand => EnqueueCommand.Execute(config.Serializer.Serialize, tx, enqueueCommand)) .Match <DequeueCommand>(dequeueCommand => DequeueCommand.Execute(config.Serializer.Deserialize, tx, dequeueCommand)) .Else(() => decoratee(tx, command)())); }
public static string Execute(Func <object, string> serializer, DocumentTransaction tx, EnqueueCommand command) { var tablename = tx.Store.Database.FormatTableNameAndEscape(command.Table.Name); var discriminator = tx.Store.Configuration.TypeMapper.ToDiscriminator(command.Message.GetType()); try { tx.SqlConnection.Execute(@$ " set nocount on; insert into {tablename} (Topic, Id, CommitId, Discriminator, Message) values (@Topic, @Id, @CommitId, @Discriminator, @Message); set nocount off;", new { command.Topic, command.Message.Id, tx.CommitId, Discriminator = discriminator, Message = serializer(command.Message) }, tx.SqlTransaction); } catch (SqlException e) { // Enqueuing is idempotent. It should ignore exceptions from primary key violations and just not insert the message. if (e.Number == 2627) { return(command.Message.Id); } throw; } return(command.Message.Id); }