2017-05-02 8 views
1

グレインが特定のIDに対してすでに存在するかどうかを確認するにはどうすればよいですか?Microsoft OrleansのGUIDでグレインが存在するかどうか確認してください

Idを持つ新しいプレーヤーグレインが作成されることを考慮して、存在しない場合はGetGrain()に渡します。既に存在するかどうかを確認する方法はわかりません。

public async Task<Guid> Create(Guid playerGuid) 
    { 
     var player = GrainClient.GrainFactory.GetGrain<IPlayerGrain>(playerGuid); 
     var gameGuid = await player.CreateGame(); 

     return gameGuid; 
    } 

答えて

5

簡単な答えは、以前にアクティブ化されているかどうかをグレインが認識できるように状態を保存することです。

オーリンズの穀物は明示的に作成または破棄されることはありません。これらの穀物は常にリクエストを処理するために利用できます。ですから、技術的には、穀物が存在するかどうかという概念は、オルレアンには適用されません。一方、私たちは、 "このIDの穀物は今までが活性化されており、前に"と尋ねることができます。

はあなたがチェックしたい場合があります2例があります。

  1. 穀物が有効にされていないが、あなたはそれが持っていることを期待しています。例:IPlayerGrainのメソッドを呼び出していますが、プレーヤーは存在しません。
  2. 穀物は以前は活性化されていましたが、そうではないと予想しています。例:私はこのプレイヤーのために新しいゲームを作成しようとしていますが、そのIDはすでに使用されています。以下のサンプルコードで

、あなたは両方のケースを見ることができます:

  1. プレイヤーが以前に作成されていない場合IPlayerGrain.CreateGame()の呼び出しが例外をスローします。私が決してCreatedを設定していないという事実を無視すると、それはある程度CreatePlayer(...)の方法で行うことができます。
  2. 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方法は変更する必要はありません。

関連する問題