Django :блокирует определенные строки в таблице

У меня есть следующий метод 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в мою модель (логическое поле )и либо просто вращать его, либо приостановить поток на несколько миллисекунд и снова проверить, но это кажется супер хакерским и грязным.Я также думал о создании хранимой процедуры, но на самом деле это не зависит от базы данных.

6
задан Kurtis Nusbaum 10 August 2012 в 20:08
поделиться