google-cloud-go icon indicating copy to clipboard operation
google-cloud-go copied to clipboard

pubsub: With exactly once delivery and message ordering enabled, message order is not mantained

Open MiquelPiza opened this issue 2 years ago • 3 comments

Client

PubSub

Expected behavior

Messages received are in the order the server delivers them

Actual behavior

Messages are reordered randomly when iterating over pendingMessages map

Additional context

On iterator.go, messageIterator.receive method, a pendingMessages map is created from the message list to remove any messages where modAck fails. After processing, a new message list is created iterating over the resulting pendingMessages object:

for _, m := range pendingMessages {
	v = append(v, m)
}
return v, nil

The order in which items are appended is not necessarily the same of the original list of messages (https://go.dev/blog/maps). Message ordering feature is thus broken

MiquelPiza avatar Feb 20 '24 09:02 MiquelPiza

triaged labels, feel free to change

noahdietz avatar Feb 21 '24 00:02 noahdietz

I'm investigating this now. Probably requires keeping track of the messages in the order they came in a slice, and using that order to return them while keeping the pendingMessages map. I think the Python library might have a similar bug so following up there as well.

hongalex avatar Feb 21 '24 21:02 hongalex

I was mistaken, the python client's behavior is different. When the receipt / lease modack happens (the first modack the client issues when a batch of messages are received), with exactly once delivery, the invalid ack_ids are kept track of in a separate array. When returning messages, the client iterates through the received messages and removes expired ack IDs.

I'll change the Go client to match this behavior.

hongalex avatar Feb 21 '24 21:02 hongalex

Fix is released in cloud.google.com/go/[email protected]

hongalex avatar Feb 29 '24 19:02 hongalex