atst/atst/models/utils.py
2019-09-17 11:03:33 -04:00

37 lines
1.0 KiB
Python

from sqlalchemy import func, sql, Interval, and_, or_
from contextlib import contextmanager
from atst.database import db
from atst.domain.exceptions import ClaimFailedException
@contextmanager
def claim_for_update(resource, minutes=30):
Model = resource.__class__
claim_until = func.now() + func.cast(
sql.functions.concat(minutes, " MINUTES"), Interval
)
rows_updated = (
db.session.query(Model)
.filter(
and_(
Model.id == resource.id,
or_(Model.claimed_until == None, Model.claimed_until < func.now()),
)
)
.update({"claimed_until": claim_until}, synchronize_session=False)
)
if rows_updated < 1:
raise ClaimFailedException(resource)
claimed = db.session.query(Model).filter_by(id=resource.id).one()
try:
yield claimed
finally:
db.session.query(Model).filter(Model.id == resource.id).filter(
Model.claimed_until != None
).update({"claimed_until": sql.null()}, synchronize_session=False)