Tastypieのドキュメントには、バンドルによってTastypieのスレッドセーフが維持されると記載されていますが、その方法と条件については説明されていません。私はコードを調べましたが、頭を包み込むほどの経験はありません。
ラウンドオブジェクト(プレイのラウンドごと)とラウンドごとに複数の状態(そのラウンドの各プレーヤーの情報)を持つゲームのプロトタイプを作成しています。各プレーヤーは、ラウンドの単語フレーズへの回答で自分の状態を更新します。次のラウンドがまだ存在しない場合は、怠惰に次のラウンドを作成するメカニズムが必要です。私は現在、プレイヤーが状態を更新したときにそのラウンドの作成をトリガーします。
複数のプレーヤーが同時に状態を更新した場合(を参照StateResource.obj_update()
) 、次のラウンドを作成する試みは衝突する可能性がありますか?obj_update
これは、ある呼び出しが次のラウンドが存在するかどうかを確認し、別の呼び出しが次のラウンドの作成を完了する前に次のラウンドを作成しようとした場合に発生する可能性があると考えていますobj_update
。ある種のミューテックスでこれを解決しますが、それが必要かどうかはわかりません。これを解決するためのTastypie-wayがあるかどうか疑問に思います。
私のコードは次のとおりです。
#models.py
class Round(models.Model):
game_uid = models.CharField(max_length=75)
word = models.CharField(max_length=75)
players = models.ManyToManyField(User)
next_round = models.OneToOneField('self',null=True,blank=True)
class PlayerRoundState(models.Model):
player = models.ForeignKey(User)
round = models.ForeignKey(Round)
answer = models.CharField(max_length=75)
#api.py
class RoundResource(ModelResource):
players = fields.ManyToManyField(UserResource, attribute='players',full=False)
states = fields.ManyToManyField('wordgame.api.StateResource',
attribute='playerroundstate_set',
full=True)
. . .
def obj_create(self, bundle, request=None, **kwargs):
bundle = super(RoundResource, self).obj_create(bundle, request,**kwargs)
bundle.obj.word = choice(words) #Gets a random word from a list
bundle.obj.round_number = 1
bundle.obj.game_uid = bundle.obj.calc_guid() #Creates a unique ID for the game
bundle.obj.save()
return bundle
class StateResource(ModelResource):
player = fields.ForeignKey(UserResource, 'player',full=False)
round = fields.ForeignKey(RoundResource, 'round')
. . .
def obj_update(self, bundle, request=None, skip_errors=False, **kwargs):
bundle = super(StateResource, self).obj_update(bundle, request,
skip_errors, **kwargs)
if bundle.obj.round.next_round is None:
new_round = Round()
new_round.word = choice(words)
new_round.round_number = bundle.obj.round.round_number + 1
new_round.game_uid = bundle.obj.round.game_uid
new_round.save()
for p in bundle.obj.round.players.all():
new_round.players.add(p)
new_round.save()
bundle.obj.round.next_round = new_round
bundle.obj.round.save()
return bundle