ozgur/python-firebase

Transaction support?

Opened this issue · 3 comments

We're in need of transaction support to update a counter in real-time:

https://www.firebase.com/docs/transactions.html

I couldn't tell for sure, but is this supported? I see put_async, but I don't think that's what we need.

@gtaylor did you guys end up implementing this?

@arg0s No. We ended up just naively retrieving + incrementing the count, with a periodic re-sync to get us back on track. Our usage case allows us to be off by a bit.

Transaction support would still be preferred, though.

The firebase-python wrapper is a Firebase REST API wrapper. The Firebase REST API doesn't support transactions. The Firebase API that supports transactions isn't documented - just the client-side javascript wrapper to that API. Until Firebase does something about this documentation (which they probably won't because it is less a user friendly web socket API, and is under flux), or builds their own python wrapper, or someone commits to continually reverse-engineering the FB protocol and to writing a python wrapper, you're not going to get access to that firebase feature from python.

That being said, here's a way to use optimistic locking and compare-and-swap concepts use the REST API to implement something like transactions:

http://stackoverflow.com/questions/23041800/firebase-transactions-via-rest-api

It is a little invasive because it involves modifying your auth rules to abort the update if the client tries to push a value that isn't an increment by one (which would mean that it got out of sync/multiple clients were updating it). To recover from the abort, you do another get and re-do whatever changes you made to the object you get back (if there is more data than the counter on the object), and re-increment. Retry a few times until you give up on number of tries, time out, or indefinitely - whatever you prefer.

This is all manual, but could be built somewhat generically using a stable data versioning convention on the FB side (like, the data will always have a property that holds an increment counter, and it is named 'blah' by default). You could use decorators/with statements on the Python side to get a syntax somewhat similar to the callback syntax of the FB javascript API.

For your use case, @gtaylor, you probably just need to build it once and don't need the generic support if you don't need to do this on more than one type of object, or don't have data on the object besides the counter.