2016-04-26 14 views
2

私はAzure Service Fabricでアクターサービスを作成しています。 Azureにデプロイすると、最初はうまくいくようです。テキストを追加して返すことができます(アクターにはWeb APIがあります)が、アイドル状態になるとGetTextsAsyncは空のコレクションを返します。アクターの状態が失われるのはなぜですか?

EDIT: 追加する前に状態が存在するかどうかを確認するコードを更新しましたが、問題は解決しません。

[StatePersistence(StatePersistence.Persisted)] 
public class TextActor : Actor, ITextActor 
{ 
    protected override async Task OnAactivateAsync() 
    { 
     if(!await StateManager.ContainsStateAsync("State")) 
     { 
      await this.StateManager.TryAddStateAsync<List<string>>("State", new List<string>()); 
     } 

    } 

    public async Task AddTextAsync(string text) 
    { 
     var texts = await this.StateManager.GetStateAsync<List<string>>("State"); 

     texts.Add(text); 

     await this.StateManager.SetStateAsync("State", texts); 
    } 

    public async Task<List<string>> GetTextsAsync() 
    { 
     return await this.StateManager.GetStateAsync<List<string>>("State"); 
    } 
} 

はEDIT2: 俳優自身が交換されたかのように思われます。 ActorIdを返すようにアクタを修正し、テキストのリストが消えると、ActorIdも新しいものに置き換えられました。

私はVoiceMailBoxサンプルのパターンに従っています。アクターはコントローラー内で静的に作成されています。それは問題ですか?

public class TextsController : ApiController 
{ 
    private static Uri serviceUri = new Uri("fabric:/TextApp/TextActorService"); 
    private static ActorId actorId = ActorId.CreateRandom(); 
    private static ITextActor textActor = ActorProxy.Create<ITextActor>(actorId, serviceUri);   


    [HttpGet] 
    public async Task<IHttpActionResult> GetTexts() 
    { 
     var texts = await textActor.GetTextsAsync(); 
     return Ok(texts);    
    } 

    //Methods omitted 
} 
+1

Re Edit 2: 'private static ActorId actorId = ActorId.CreateRandom();'という行は悪い考えです。 WebApiステートレスサービスの各インスタンスは、異なる「ActorId」で終了します。 1つのインスタンスしか持たない場合でも、インスタンスを再起動する場合、置換インスタンスは 'textActor'に対して異なる' ActorId'を持ちます。定数 'ActorId'を使用して問題が解決するかどうかを確認します。 'private static ActorId actorId = new ActorId(0);' –

+0

@NickBarrettのようなものが私の主な問題でした。 – Landrew

答えて

3

これは、あなたがOnActivate()メソッドを持っているコードである - それは、新しいリストに状態をリセットします。

OnActivate()メソッドは、アクターで複数回呼び出すことができます。特定のアクターを初めて作成するときに呼び出されるだけではありません。アクタを一定期間使用しないと、アクタが無効になります(OnDeactivateAsync()メソッドが呼び出されます)。しかし、俳優への新しい呼び出しが行われると、再びアクティブになります。

それは俳優のライフサイクルhttps://azure.microsoft.com/en-gb/documentation/articles/service-fabric-reliable-actors-lifecycle/

+0

私はOnActivateAsyncへの呼び出しを削除し、代わりにStateManager.GetOrAddStateAsyncをGetメソッドとAddメソッド内から使用します。不思議なことに、その行動は残っている。 – Landrew

+0

問題を解決しましたか?そうでない場合は、更新されたコードを投稿する価値があります。 – charisk

+0

解決されていませんが、私は最後の試みを反映するようにコードを更新しました。 – Landrew

1

について少し読む価値があるかもしれない方法についての代わりに、必要に応じて、あなたはそれはあなたのAddTextAsync(string text)方法で初期化し、あなたの状態を初期化するためにOnActivate()メソッドを使用しての?

public async Task AddTextAsync(string text) 
{ 
    // Try and get the state 
    var conditionalTexts = await this.StateManager.TryGetStateAsync<List<string>>("State"); 
    // If it exists, use it, otherwise create a new one 
    List<string> texts = conditionalTexts.HasValue ? conditionalTexts.Value : new List<string>(); 
    // Make your changes 
    texts.Add(text); 
    // Save the state 
    await this.StateManager.SetStateAsync("State", texts); 
} 
+0

これは私がテストした多くの変種の1つですが、すべて同じ結果が残っています。しばらくするとテキストが消えます。 – Landrew

+0

カスタムクラスの 'string'や' List <> 'の' List <> 'を使っていますか?それがクラスなら、必要な '[DataContract]'と '[DataMember]'属性で設定していますか? –

関連する問題