RE: [DDD/CQRS] How to implement delete and delete-after-N-days inevent sourcing

322 views
Skip to first unread message

Kijana Woodard

unread,
Aug 21, 2014, 9:26:35 AM8/21/14
to ddd...@googlegroups.com
That's just an, unfortunate, implementation detail.

The scheduled job run itself is the "future message".

From: Michael Schmidt
Sent: ‎8/‎21/‎2014 3:03 AM
To: Greg Young; ddd...@googlegroups.com
Cc: Ron Liu; Kasey Speakman
Subject: RE: [DDD/CQRS] How to implement delete and delete-after-N-days inevent sourcing

Except its not a "message" its a db script. Our carts are kept in a relational db using XML. Don't even get me started.

Since its db code, compares a date, deletes a record, I have a hard time calling it a message. A command yes "delete cart"...

Sent from my Windows Phone

From: Greg Young
Sent: 8/19/2014 9:07 AM
To: ddd...@googlegroups.com
Cc: Ron Liu; Kasey Speakman
Subject: Re: [DDD/CQRS] How to implement delete and delete-after-N-days in event sourcing

"Yes, it does seem like a poor use of future messages. We don't use any of this (ddd) , but our carts are expired by deletion by a job. Old school."

Umm what is your job? Its just a specific (poorly done) implementation of a future message no?


On Tue, Aug 19, 2014 at 11:34 AM, Michael Schmidt <mikeyw...@gmail.com> wrote:
Yes, it does seem like a poor use of future messages. We don't use any of this (ddd) , but our carts are expired by deletion by a job. Old school.


Sent from my Windows Phone

From: Ron Liu
Sent: 8/15/2014 7:43 AM
To: ddd...@googlegroups.com
Cc: Kasey Speakman

Subject: Re: [DDD/CQRS] How to implement delete and delete-after-N-days in event sourcing

Hi Michael, 

I think I will expire the cart only based on createdOn, which means touching again will not extend. 

If I really want to extend, based on Grey's future message talk, I guess we should add a number(like a sign) into message schema, so 
1. it sent a future message with 1 and expiry date is N day after yesterday, assume cart was created yesterday;
2. when user touch it
    a. send a message straight away with -1 and date is N days after now which means cancel any future message whose date is before N days after now
    b. send another future message again with 1 and date is N days after now. 

Hopefully it make sense.

By the way, I feel a little bit it is overkilled to use future message to expire a cart, I am not sure if projection can do the same job. 


Cheers,
Ron 


On Sat, Aug 16, 2014 at 12:18 AM, Michael Schmidt <mikeyw...@gmail.com> wrote:
So if you use a future message, and the user touches that cart again, do you cancel the message so the user has another X days to keep their cart? or do you copy the cart to a new cart. If you do that you can delete the old cart right away.

I guess I need to see the video. Read some more about future messages.

Sent from my Windows Phone

From: Kasey Speakman
Sent: 8/15/2014 6:33 AM
To: ddd...@googlegroups.com
Subject: Re: [DDD/CQRS] How to implement delete and delete-after-N-days in event sourcing



On Fri, Aug 15, 2014 at 1:39 AM, Ron Liu <ronl...@gmail.com> wrote:
Hi Kasey, 

Could you give me a link I can learn from? 

Thanks,
Ron




On Fri, Aug 15, 2014 at 12:41 AM, Kasey Speakman <ka...@cornerspeed.com> wrote:
I recall him saying that he starts with projected views and letting a user be the process manager. Then automation options are evaluated as the process solidifies.


On Thursday, August 14, 2014 9:36:40 AM UTC-5, Kijana Woodard wrote:
Fwiw, I think I remember Rinat Abdullin talking about falling out of favor with storing "future messages" in a separate timeout service. I was never very clear on the replacement, but it might have been just keeping all the timeouts in memory.


On Thu, Aug 14, 2014 at 9:18 AM, Greg Young <gregor...@gmail.com> wrote:
Some event stores such as event store support this internally $maxage on stream. A more generic solution can be seen however in process managers and delayed messaging see my talk from dddx this year on skills after website


On Thursday, August 14, 2014, Dustin Wheeler <mdwh...@ncsu.edu> wrote:
Hey Ron!

The case you want to delete an aggregate, you might store a deleted property to maintain enough state to be able to hold the hypothetical invariant that the only command that can be issued from that point on to this specific aggregate is a "RestoreAggregateCommand".  You might have the repository wrapping an event store return null if it determines that an aggregate (after having all events applied to it) had a "deleted property" of "true".  Either way, what comes out of the event store is events, that's it.  They get applied to a specific aggregate as part of its history by a repository and the repository exposes the aggregate according to the constraints of its interface.

In the case you wanted to implement "delete after N days", I have in the past used sagas to pull this off.  Essentially each saga becomes an instance of a workflow that is defined by the behaviour you're seeking.  In this case, the saga would abstractly "recognize how many days have passed since creation" and then simply send a command to your application, deleting the item.  Greg Y. has a post on these forums I'll try to hunt down that describes this in more detail.  If I can't find it, I'll try to elaborate more.  But essentially, it's a long-running process that abstracts the rule you've described and simply sends a DeleteThisThingCommand when it's time (which is great because it just fits with the rest of your architecture, usually)

On Thursday, August 14, 2014 7:51:48 AM UTC-4, Ron Liu wrote:
Hi Guys, 

I am new to event sourcing, recently I am trying on my e-commerce project. Right now I am struggling with how to delete or delete-after-N-days cases. 

1. Delete:
I guess I should introduce a delted property in AbstractEventSourcedAggregate, and when delete command comes, just set this property to true. And when eventstore try to get an aggregate which has been set to deleted, it should return null. Is it right way to do it? 

2. Delete-after-N-days:
The case is shopping cart. we should delete cart items after N days. But who should send a command which will generate this events and when?


Thanks,
Ron

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Studying for the Turing test

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "DDD/CQRS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dddcqrs/R5kZce_WCJg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to dddcqrs+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Best Regards,
Ron Liu
Mobile: +61 4 1163 7727
Email: ronl...@gmail.com

--
You received this message because you are subscribed to a topic in the Google Groups "DDD/CQRS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dddcqrs/R5kZce_WCJg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to dddcqrs+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "DDD/CQRS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dddcqrs/R5kZce_WCJg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to dddcqrs+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Best Regards,
Ron Liu
Mobile: +61 4 1163 7727
Email: ronl...@gmail.com

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Studying for the Turing test

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michael Schmidt

unread,
Aug 21, 2014, 9:58:20 AM8/21/14
to Kijana Woodard, ddd...@googlegroups.com
Yes


Sent from my Windows Phone

From: Kijana Woodard
Sent: 8/21/2014 6:26 AM
To: ddd...@googlegroups.com

Ron Liu

unread,
Aug 22, 2014, 12:12:59 PM8/22/14
to ddd...@googlegroups.com
IMO, The difference between scheduled job and future message are: 
1. If we doesn't care the accuracy, scheduled job is a better option, because it is easy. Like cart expiration case, the requirement should be expired in 2 hours, but it doesn't matter if it really expired in 2 hours and 1minute.  

2. If we do care the accuracy, has to use future message, like reserve patter used in movie ticket sale case, the requirement is the order should be expired in exact 15 minutes

Kijana Woodard

unread,
Aug 22, 2014, 12:21:27 PM8/22/14
to ddd...@googlegroups.com
A future message implemented via "messages on a broker queue" doesn't guarantee time exactness either. The message still has to be enqueued, delivered, and processed. That can be delayed for any number of reasons.

In the above case, the batch job could be run every minute. 

You can optimize this by keeping the next n messages in memory. 

No matter how you implement it, it's still a future message.

Ron Liu

unread,
Aug 22, 2014, 1:26:47 PM8/22/14
to ddd...@googlegroups.com
Yes, "messages on a broker queue" doesn't guarantee accuracy, I didn't realised that. As Greg just said message are assured to come on time or after.

When I dive in, I think I may be confused by the same terminology in requirement level and implementation level. 

Requirement Level:
#R Some thing need to happen in certain future time: I thought it was called future msg

Implementation Leve:
#PM "Delayed message on broker queue": I thought it was future msg
#PT "System Timer": I thought it was called scheduled task

For #R,  it can be implemented by 
#1.  #PM: it is straight forward
#2.  #PT: use timer to check if it's timeout, if it is do something
#3. I just find out, is it good to do something like below (use #PM to simulate a timer)?, give cart expiration as a example
     function Handle(CertainEvent event) {
          Check all carts if expired
          Bus.Defer(event, 10min)
     }

So when you say "No matter how you implement it, it's still a future message.", actually means: ..., it's still some thing need to happen in certain future time .

Sorry I may make thing over-complicated.

Thanks,
Ron

Kijana Woodard

unread,
Aug 22, 2014, 2:37:49 PM8/22/14
to ddd...@googlegroups.com
Define "certain time".

Millisecond granularity?
One minute? What if it's two?
How exact does this _really_ need to be?

If you do "Bus.Defer(event, 10min)", when the message comes back, it _could_ be #100,000,000 in the queue.
If that's the case, it might take some time until it's processed. 
Does that make a difference?

The key is to make you requirements explicit [esp SLA] and architect to handle. On top, establish a contigency plan for unexpected scenarios [how will you scale horizontally?]. Isolate important processing from low priority processing [orders vs email newsletter subs].

Bus.Defer more than likely stores data in a broker/database, polls it to see if something has expired and then puts a message on a queue.

This is roughly equivalent to storing records in a database and having a windows scheduled task run every n minutes that queries for expiry. That job could then put messages on a queue or do the work itself.

That is roughly equivalent to holding a list of timeouts in memory, saving them to disk/db for recovery, and, in a loop, check for expiry, send relevant messages or do work, then thread.sleep.

They're all lead to the same result. Implementation details are chosen based on needs/skills/available technology/etc.

Greg Young

unread,
Aug 22, 2014, 2:44:20 PM8/22/14
to ddd...@googlegroups.com
If you do "Bus.Defer(event, 10min)", when the message comes back, it _could_ be #100,000,000 in the queue.
If that's the case, it might take some time until it's processed. 
Does that make a difference?

You could also be down :)

Kijana Woodard

unread,
Aug 22, 2014, 5:13:45 PM8/22/14
to ddd...@googlegroups.com
Right. Missed the obvious. LOL.

Ron Liu

unread,
Aug 22, 2014, 7:30:38 PM8/22/14
to ddd...@googlegroups.com
Yes, they all lead to the same results, it will come on time or after, and hard to say which one is better, it is case by case.



To unsubscribe from this group and all its topics, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages