在Microsoft Orleans中检查GUID是否存在颗粒

时间:2017-05-02 18:41:55

标签: orleans

如何检查某个ID是否已存在?

考虑到下面的内容会创建一个新的播放器粒度,如果它不存在,我会传入GetGrain(),我不知道如何检查是否已经存在。

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

        return gameGuid;
    }

1 个答案:

答案 0 :(得分:7)

简短的回答是存储一些状态,以便谷物知道它是否先前已被激活。

奥尔良的谷物永远不会被明确地创建或销毁:它们始终可用于处理请求。因此,从技术上讲,谷物是否存在的概念并不适用于奥尔良。另一方面,我们可以在&#34;之前询问&#34;是否已经激活的谷物。

您可能需要检查两种情况:

  1. 谷物从来没有被激活,但是你期待它已经被激活了。例如:我在IPlayerGrain上调用方法,但播放器不存在。
  2. 之前已经激活了谷物,但您预计它还没有。例如:我试图为这个玩家创建一个新游戏,但该游戏已被用作。
  3. 在下面的代码示例中,您可以看到两种情况:

    1. 如果之前从未创建过播放器,则对IPlayerGrain.CreateGame()的调用将抛出异常。忽略我永远不会设置Created的事实,这可以通过某种CreatePlayer(...)方法完成。
    2. 如果已经创建了游戏,则对IGameGrain.TryCreateGame(player)的调用将返回false。在这种情况下,IPlayerGrain.CreateGame()将继续循环,直到找到一个尚未创建的游戏。使用Guid ID时,您不太可能看到碰撞,但我理解谨慎的愿望 - 只是让星星对齐并对你不利。
    3. 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方法无需更改。