Fix interleaved repo delete with RAC via a transaction

The RepositoryActionCount table can have entries added while a repository deletion is in progress. We now perform the repository deletion under a transaction and explicitly test for RAC entries in the deletion unit test (which doesn't test interleaving, but it was missing this check).

Fixes #494
This commit is contained in:
Joseph Schorr 2015-09-16 15:34:20 -04:00
parent d6f4e0c7b2
commit 30379a2dd8
3 changed files with 36 additions and 13 deletions

View file

@ -119,6 +119,7 @@ db = Proxy()
read_slave = Proxy()
db_random_func = CallableProxy()
db_for_update = CallableProxy()
db_transaction = CallableProxy()
def validate_database_url(url, db_kwargs, connect_timeout=5):
@ -164,6 +165,10 @@ def configure(config_object):
if read_slave_uri is not None:
read_slave.initialize(_db_from_url(read_slave_uri, db_kwargs))
def _db_transaction():
return config_object['DB_TRANSACTION_FACTORY'](db)
db_transaction.initialize(_db_transaction)
def random_string_generator(length=16):
def random_string():
@ -373,14 +378,15 @@ class Repository(BaseModel):
return sorted_models.index(cmp_fk.model_class.__name__)
filtered_ops.sort(key=sorted_model_key)
for query, fk in filtered_ops:
model = fk.model_class
if fk.null and not delete_nullable:
model.update(**{fk.name: None}).where(query).execute()
else:
model.delete().where(query).execute()
with db_transaction():
for query, fk in filtered_ops:
model = fk.model_class
if fk.null and not delete_nullable:
model.update(**{fk.name: None}).where(query).execute()
else:
model.delete().where(query).execute()
return self.delete().where(self._pk_expr()).execute()
return self.delete().where(self._pk_expr()).execute()
class Star(BaseModel):
user = ForeignKeyField(User, index=True)