6

I'm writing a web app which allows users to upload real-estate listings. Part of what this does is allow them to upload photos of the property they're listing.

I'm using a micro-service type approach so there's a property media service which handles all the uploading of media, querying of what media are available for each property, etc.

However because I need fast searching and display of a property page without calling off to 7 or 8 services, I also maintain an Azure DocumentDB collection of properties, where each document holds everything about the specific property needed to support search and binding of the property details page.

So far so good.

I opted for an event sourcing pattern whereby when a new photo was uploaded, I simply raised an event onto an Azure Service Bus topic. There was a subscription to this topic which was a trigger to an Azure Function that would load the document, update it with the uploaded image details, and save it.

It worked - but then I have a parallelism / concurrency problem whereby if a user uploads 10 images, it raises 10 events onto the topic. With the nature of Azure Functions, it might spin up 10 processes concurrently each handing a message.

Because Azure DocumentDb does not support partial document updates, the Azure Function takes these steps:

  • Loads the document
  • Adds a child to the images collection
  • Saves the document

I've recently noticed that I don't get a reliable update when uploading multiple images. Maybe only 6 of the 10 will show in the DocumentDb. The logs of the function show all 10 executions were successful, so I can only assume here that I've been the victim of them running in parallel and one update overwriting another.

To get around it, I've made it so that the media service doesn't raise an event any more, but it just updates the DocumentDb itself. But I'm not really happy with this because it's not really its responsibility in my mind. It's solved the problem for now - but I liked the event-sourcing and Azure Functions updating the document as a better design.

Are there any better options for me? I considered that I could add a document to the DocumentDb collection in the Azure Function instead of updating one "master document" but then it'll mean more work in the property details page to aggregate it together.

Have I missed a trick?

1 Answer 1

1
+50

So, my understanding of Event Sourcing, is that you recreate your object from saved events rather than the traditional deserializing the object state. It sounds like you are not really doing that though.

Because the order of the events is usually important. This necessitates some form of manual transaction, where by you assign sequential event ids, or a version number and can tell if another event has happened while you were processing the event you are working on. ie.

  • Load Doc
  • read old version number/last event id
  • add image with event id
  • update version number
  • overwrite doc IF the version number is the same/no more events have been added
  • IF the version has changed since you started, redo the operation.

Obviously this doesnt work well if you have lots of collisions as you are always redoing steps. Plus you still need some sort of DB supported transaction for that final step.

However, I see that DocumentDb does support transactions:

Does DocumentDB support ACID transactions?

Yes, DocumentDB supports cross-document transactions expressed as JavaScript stored procedures

I would suggest you create a simple reusable transaction which just checks the document version number is as expected. You can then use that with all your events.

1
  • That makes perfect sense. Thanks for the reply. I can't award the bounty just yet (need to wait 3 hours) but I will do this when I can.
    – bgs264
    Commented Mar 7, 2017 at 14:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.