Pergunta

Ok, so here is the problem. We are using CQRS with Event Sourcing and we are using event stream per commit sequence of aggregate instance. And every stream is persisted with it's respective date of creation,but the thing is that all of this happens way too fast, meaning that some of the aggregate event streams, which are part of some process (registrations, notifications etc. ), comes out with the exact same date. So when we have to replay the events,ordering the streams by creation date doesnt work beacouse there are streams of events which are dependent in time, but they happenend so fast that it looks like they happend parallel (meaning we used DateTime.UtcNow and the dates are equal to nanosecond).

For those who don't know what CQRS or Event Sourcing is

Imagine that you have a resource List and every item has its creation date. And its crutial to know the order of creation of the items in the List. Have in mind that there are multiple threads creating and adding items in the list. The problem is that when a thread has to create and add two items in the list their dates of creation matches u cant order them by date correctly. Btw the pc matters on my pc DateTime.Now is not equals to DateTime.Now on the server it is. Actually on a coworkers pcadding 25000 times DateTime.Now to a list results that the first and the last element of the list are equals to the nanosecond(exact match)

Foi útil?

Solução

A timestamp is a useful piece of metadata. It's not -- as you've discovered -- a reliable ordering criterion. Imagine you come up with some solution on your machine, but now have to use two machines? Can you keep their clocks synchronized within a nanosecond? Less?

In event sourcing, the typical guarantee is only that events are sorted within a single stream, e.g. one aggregate. This is your transaction guarantee anyway. Why not just use an integer to track each event's sequence within a stream? Your aggregate can generate it, since it's been tracking all events anyway.

If you want ordering across streams, you'll have to either generate that sequence number centrally (with the coupling that represents), or accept that multiple reads of multiple streams will not always return events within the same order, just that events within one stream should be sorted.

Outras dicas

You can get an accurate number which you can use as a timestamp by calling the Windows API's QueryPerformanceCounter() which should give you a consistent value between threads with a very high resolution.

Of course, this only gives you values that are relevant to one particular computer; it can't be used if you want to compare the timestamps created on two different computers.

However, note this (from the Windows API documentation):

On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL).

(I've not encountered the above bug on any hardware myself.)

You can get at the performance counter via C# as follows:

public long PerformanceCounter()
{
    long result;
    QueryPerformanceCounter(out result);
    return result;
}

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top