Quick question regarding PersistentSubscriptionAckEvents and PersistentSubscriptionNackEvents

Hi everyone.

I have almost finished to implement competing consumers for EventStore Haskell driver and I’m wondering how

the list/array of GUID is actually serialized for Ack/Nack actions.

(1) Is the array just ‘flatten’ to a single byte array or (2) do you place some kind of separator between each element ? GUID has fixed size so I would guess it’s (1) but just want to be sure.

Thanks for your time

Yorick

Hah, this is a slightly awkward artefact of three things:

  1. .NET ‘serializes’ UUIDs (it calls them GUIDs) in a way which can only be described as crazy. I have no doubt that it was done for ‘backwards compatibility’ but that’s no excuse really.

  2. This wasn’t discovered until in .NET version of protocol buffers until such time as it was too late to change.

  3. The initial ES client was .NET so it wasn’t noticed until it was too late.

I’m not sure how you’d do it in Haskell, but in Java this will create a UUID from a byte array containing the .NET serialisation:

private static final int[] mostOrder = new int[]{3,2,1,0,5,4,7,6};

private static UUID uuidFromCrazyEndian(byte[] dotNetEncodedGuid) {

long most = 0;

long least = 0;

for (int i : mostOrder) {

most = (most << 8) | (dotNetEncodedGuid[i] & 0xFF);

}

for (int i = 8; i < 16; i++) {

least = (least << 8) | (dotNetEncodedGuid[i] & 0xFF);

}

return new UUID(most, least);

}

Here is the same thing in Go:

var order = […]int{3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15}

func crazyEndianToUUID(netEncoded []byte) uuid.UUID {

uuidBytes := make([]byte, 16)

for i := 0; i < len(order); i++ {

uuidBytes[i] = netEncoded[order[i]]

}

return uuidBytes

}

However, you don’t actually need to make these UUIDs except for debugging/reporting purposes - you’ll get the same bytes back but the display won’t correlate.

Hope this helps, great work with the client!

Cheers,

James

Hi James,

Thanks for your answer but I think we had a misunderstanding :slight_smile:

The Haskell client is almost on par with its .NET counterpart now. The only thing it doesn’t do right know is SSL communication with the server and it also lacks of proper logging facility.

But my question was about ack-ing or nak-ing events when using a persistent subscription. notifyEventsProcessed and notifyEventsFailed

allow the user to pass a list of GUID. In Haskell we also call those UUID and fortunately, there was already a package that handled that for me.

When having a look on the EventStore protobuf file, we can see that PersistentSubscriptionAckEvents and PersistentSubscriptionNackEvents

store that list of GUID/UUID as a simple byte string. My question was how that list is handled in order to fit in a flat byte string. My first assumption

was, considering that GUID/UUID has a fixed size, I assume that every GUID/UUID of that array would be concatenated without any separator in between.

My second guess was that ES server expects a separator between two GUID/UUID. I went with my first guess so far and it looks like it works but I need

to be sure about this :-).