У меня есть следующий метод django:
def setCurrentSong(request, player):
try:
newCurrentSong = ActivePlaylistEntry.objects.get(
song__player_lib_song_id=request.POST['lib_id'],
song__player=player,
state=u'QE')
except ObjectDoesNotExist:
toReturn = HttpResponseNotFound()
toReturn[MISSING_RESOURCE_HEADER] = 'song'
return toReturn
try:
currentSong = ActivePlaylistEntry.objects.get(song__player=player, state=u'PL')
currentSong.state=u'FN'
currentSong.save()
except ObjectDoesNotExist:
pass
except MultipleObjectsReturned:
#This is bad. It means that
#this function isn't getting executed atomically like we hoped it would be
#I think we may actually need a mutex to protect this critial section :(
ActivePlaylistEntry.objects.filter(song__player=player, state=u'PL').update(state=u'FN')
newCurrentSong.state = u'PL'
newCurrentSong.save()
PlaylistEntryTimePlayed(playlist_entry=newCurrentSong).save()
return HttpResponse("Song changed")
По сути, я хочу, чтобы для данного player
существовал только один ActivePlaylistEntry, который имеет состояние воспроизведения )'PL' (в любой момент времени. Однако у меня были фактически случаи, когда в результате быстрого вызова этого метода два раза подряд я получал две песни для одного и того же проигрывателя с состоянием 'PL'. Это плохо, поскольку у меня есть другая логика приложения, основанная на том факте, что у проигрывателя в любой момент времени воспроизводится только одна песня (, плюс семантически не имеет смысла воспроизводить две разные песни одновременно на одном и том же устройстве. игрок ). Есть ли способ сделать это обновление атомарным? Простой запуск метода как транзакции с декоратором on_commit_success
не работает. Есть ли способ заблокировать таблицу для всех песен, принадлежащих конкретному плееру? Я думал о том, чтобы добавить столбец lock
в мою модель (логическое поле )и либо просто вращать его, либо приостановить поток на несколько миллисекунд и снова проверить, но это кажется супер хакерским и грязным.Я также думал о создании хранимой процедуры, но на самом деле это не зависит от базы данных.