Reputation: 16563
I have a GAE model with several methods that update entities with transactions. Something like this:
class MyModel(ndb.Model):
@staticmethod
@ndb.transactional
def update_foo(ekey):
entity = ekey.get()
entity.foo = "x"
entity.put()
@staticmethod
@ndb.transactional
def update_bar(ekey):
entity = ekey.get()
entity.bar = "y"
entity.put()
To clean up my code, I was thinking, I could centralize the code that does updates with transactions. Something like this:
class MyModel(ndb.Model):
@staticmethod
@ndb.transactional
def update_tx(ekey, **kwargs):
entity = ekey.get()
for prop, value in kwargs.iteritems():
setattr(entity, prop, value)
enitty.put()
def update_foo(self):
self.update_tx(self.key, foo="x")
def update_bar(self):
self.update_tx(self.key, bar="y")
Is this a reasonable idea, or are there dangers in this approach that I haven't considered?
Upvotes: 0
Views: 54
Reputation: 5276
It's reasonable. It really depends on your use case.
I actually had something similar in place, but more and more I have to special case my update_tx()
for each entity type to the point that only 1 or 2 of my ~10 models still use it, because there is almost always other logic that needs to be executed.
That logic could happen outside of this function, but I often want that to happen in the same transaction.
That aside, one thing it doesn't seem to handle is needing to update a batch of entities in a single transaction, so your pseudo code would need to look more like this if that's important to you:
class MyModel(ndb.Model):
def update_properties(self, **kwargs):
for prop, value in kwargs.iteritems():
setattr(self, prop, value)
@staticmethod
@ndb.transactional(xg=True)
def update_txs(keys, updates):
# keys is an array of ndb.Key()s,
# updates is an array of the same size, containing **kwargs for each key
entities = ndb.get_multi(keys)
for index, entity in enumerate(entities):
entity.update_properties(**updates[index])
ndb.put_multi(entities)
@classmethod
def update_tx(cls, ekey, **kwargs):
cls.update_txs([ekey], [kwargs])
def update_foo(self):
self.update_tx(self.key, foo="x")
def update_bar(self):
self.update_tx(self.key, bar="y")
Upvotes: 1