Excuse me, my bill does not match my order

exactly-once.github.io

twitter.com/SzymonPobiega

linkedin.com/in/SzymonPobiega

Domain-Driven Design

Event Sourcing

Pierogi

Autor: Stako (File:Ruskie.jpg) [GFDL lub CC-BY-SA-3.0], Wikimedia Commons

Network is reliable

Exactly once delivery in face of failures

Exactly once delivery

Exactly once processing

Pierogi

Autor: Stako (File:Ruskie.jpg) [GFDL lub CC-BY-SA-3.0], Wikimedia Commons

"Just make your logic idempotemt"

-- Twitter Trolls

\(f(f(x)) = f(x)\)


public class ConfirmOrderHandler 
	: IHandleMessages<ConfirmOrder>
{
	public Task Handle(ConfirmOrder msg, 
		IMessageHandlingContext context)
	{
		/*business logic*/

		context.Publish(evnt);
	}
}
					

						
System.Messaging.MessageQueueException (0x80004005): 
↳ Insufficient resources to perform operation.
↳ at System.Messaging.MessageQueue.SendInternal(Object obj, 
↳ MessageQueueTransaction internalTransaction, 
↳ MessageQueueTransactionType transactionType)
						
					
							
System.Exception: Channel has been closed: AMQP close-reason, 
↳ initiated by Library, code=541, text="Unexpected Exception", 
↳ classId=0, methodId=0, cause=System.Net.Sockets.SocketException
↳ A connection attempt failed because the connected party did not 
↳ properly respond after a period of time, or established 
↳ connection failed because connected host has failed to respond
							
						

Persist state✔️

Publish event🔥

Publish event

Persist state

						
Transaction (Process ID) was deadlocked on lock 
↳ resources with another process and has been 
↳ chosen as the deadlock victim. 
↳ Rerun the transaction.
						
					

"Just make your logic idempotemt"

-- Twitter Trolls

Framing the problem

  • Don't lose messages 🗑️

  • Apply state change only once 👯‍♂️

  • Don't leak non-durable state 👻

If you could add quantity to the order lines

that would be GREAT!

Framing the problem

  • Don't lose messages 🗑️

  • Apply state change only once 👯‍♂️

  • Don't leak non-durable state 👻

Apply state change only once

"... we want an endpoint to produce observable side-effects equivalent to some execution in which each logical message gets processed exactly-once"

-- Tomasz Masternak

"Just make your logic deterministic"

-- Twitter Trolls

If you could add FirstItemAdded event

that would be GREAT!


public class AddItemHandler 
	: IHandleMessages<AddItem>
{
	public Task Handle(AddItem message, 
		IMessageHandlingContext context)
	{
		/*...*/
		if (order.Lines.Count == 1)
		{ 
			context.Publish(
				new FirstItemAdded(/*...*/));
		}
	}
}
					

Receive AddItem 123✔️

Check if not a duplicate✔️

Add OrderLine to Order and persist✔️

Publish ItemAdded✔️

Count OrderLines 1

Publish FistItemAdded🔥

Put AddItem 123 back to queue✔️

Receive AddItem 234✔️

Check if not a duplicate✔️

Add OrderLine to Order and persist✔️

Publish ItemAdded✔️

Count OrderLines 2

Publish FistItemAdded

Receive AddItem 123✔️

Check if not a duplicate👯‍♂️

Add OrderLine to Order and persist

Publish ItemAdded✔️

Count OrderLines 2

Publish FistItemAdded

Business logic is executed correctly✔️

Message publishing is based on an incorrect state ❌

Consistent messaging

Re-publish messages based on historic state

Durably store outgoing messages

If you could finally get that code to work

that would be GREAT!

Do you know why are those messages processed in the wrong order?

The End ?

exactly-once.github.io

Thank you!

github.com/exactly-once

exactly-once.github.io

twitter.com/SzymonPobiega

linkedin.com/in/SzymonPobiega