簡単な答えは、以前にアクティブ化されているかどうかをグレインが認識できるように状態を保存することです。
オーリンズの穀物は明示的に作成または破棄されることはありません。これらの穀物は常にリクエストを処理するために利用できます。ですから、技術的には、穀物が存在するかどうかという概念は、オルレアンには適用されません。一方、私たちは、 "このIDの穀物は今までが活性化されており、前に"と尋ねることができます。
はあなたがチェックしたい場合があります2例があります。
- 穀物が有効にされていないが、あなたはそれが持っていることを期待しています。例:
IPlayerGrain
のメソッドを呼び出していますが、プレーヤーは存在しません。
- 穀物は以前は活性化されていましたが、そうではないと予想しています。例:私はこのプレイヤーのために新しいゲームを作成しようとしていますが、そのIDはすでに使用されています。以下のサンプルコードで
、あなたは両方のケースを見ることができます:
- プレイヤーが以前に作成されていない場合
IPlayerGrain.CreateGame()
の呼び出しが例外をスローします。私が決してCreated
を設定していないという事実を無視すると、それはある程度CreatePlayer(...)
の方法で行うことができます。
IGameGrain.TryCreateGame(player)
の呼び出しは、ゲームがすでに作成されている場合はfalseを返します。その場合、IPlayerGrain.CreateGame()
は作成されていないゲームが見つかるまでループし続けます。 Guid
のIDを使用すると、衝突する可能性はほとんどありませんが、私は慎重になりたいと思っています。
public interface IPlayerGrain : IGrainWithGuidKey
{
Task<Guid> CreateGame();
}
public class PlayerState
{
public bool Created { get; set; }
}
public class PlayerGrain : Grain<PlayerState>, IPlayerGrain
{
public async Task<Guid> CreateGame()
{
if (!this.State.Created)
throw new InvalidOperationException("Player does not exist.");
var thisPlayer = this.AsReference<IPlayerGrain>();
var created = false;
var gameId = default(Guid);
while (!created)
{
// Get a new, random game grain
gameId = Guid.NewGuid();
// Try to create a game.
created = await this.GrainFactory.GetGrain<IGameGrain>(gameId)
.TryCreateGame(thisPlayer);
// If the game was successfully created, break out and return the id.
// Otherwise, keep looping.
}
return gameId;
}
}
public interface IGameGrain : IGrainWithGuidKey
{
// Returns true if game was created, false otherwise.
Task<bool> TryCreateGame(IPlayerGrain player);
}
public class GameState
{
public IPlayerGrain Player { get; set; }
}
public class GameGrain : Grain<GameState>, IGameGrain
{
public async Task<bool> TryCreateGame(IPlayerGrain player)
{
// If this grain already has a player, return false.
if (this.State.Player != null) return false;
// Otherwise, set the player, write it to storage, and return true.
this.State.Player = player;
await this.WriteStateAsync();
return true;
}
}
あなたの質問でCreate
方法は変更する必要はありません。