私は次のジャンゴメソッドを持っています:
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
1 つだけになるようにしたいと考えています。しかし、このメソッドを2回続けて素早く呼び出した結果、同じプレーヤーの曲を2つ取得し、状態が. プレイヤーが常に 1 つの再生中の曲しか持っていないという事実に依存する他のアプリケーション ロジックがあるため、これは悪いことです (さらに、意味的には、同じプレイヤーで同時に 2 つの異なる曲を再生することは意味がありません)。 . この更新をアトミックに行う方法はありますか? メソッドをトランザクションとして実行するだけですActivePlaylistEntry
'PL'
'PL'
on_commit_success
デコレータが機能していないようです。特定のプレーヤーに属するすべての曲のテーブルをロックする方法はありますか? モデル (ブール値フィールド) に列を追加して、lock
それをスピンするか、スレッドを数ミリ秒間一時停止して再度チェックすることを考えていましたが、これらは非常にハックで汚れているように感じます。ストアド プロシージャを作成することも考えていましたが、それは実際にはデータベースに依存しません。