4

I am following the advice in Service Fabric spawn actor on startup for spawning a couple of actors at service start. I have a custom ActorService subclass with the following RunAsync override:

internal sealed class InternalCustomActorService : ActorService
{
  protected async override Task RunAsync(CancellationToken cancellationToken)
  {
    await base.RunAsync(cancellationToken);

    for(int i = 0; i < 10; i++)
    {
      ICustomActor proxy = ActorProxy.Create<ICustomActor>(new ActorId(i));
      await proxy.StartAsync();
    }
  }
...

The class is registered in Program.cs as follows:

    ActorRuntime.RegisterActorAsync<CustomActor>(
       (context, actorType) => new InternalCustomActorService(context, actorType, () => new CustomActor())).GetAwaiter().GetResult();

However, I am getting the following exception calling proxy.StartAsync() method:

FatalExecutionEngineError occurred
  HResult=-2146233088
  Message=One or more errors occurred.
  Source=Microsoft.ServiceFabric.Services
  StackTrace:
       at Microsoft.ServiceFabric.Services.Communication.Client.ServicePartitionClient`1.<InvokeWithRetryAsync>d__7`1.MoveNext()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.ServiceFabric.Services.Remoting.Client.ServiceRemotingPartitionClient.<InvokeAsync>d__8.MoveNext()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.ProxyBase.<InvokeAsync>d__0.MoveNext()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.ProxyBase.<ContinueWith>d__b.MoveNext()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
       at CustomActorService.InternalCustomActorService.<RunAsync>d__2.MoveNext() in C:\_data\Master\CONSTABLE2\Apps\BSP\Research\ServiceFabric\CustomActorServiceApp\CustomActorService\InternalCustomActorService.cs:line 47
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.ServiceFabric.Services.Runtime.StatefulServiceReplicaAdapter.<ExecuteRunAsync>d__e.MoveNext()
  InnerException: 
       HResult=-2147467263
       Message=Interface id '1830616258' is not implemented by object 'CustomActorService.InternalCustomActorService'
       Source=Microsoft.ServiceFabric.Services
       InnerException: 

The sample project is on GitHub here https://github.com/PaloMraz/CustomActorServiceApp

My question is: what am I doing wrong?

EDIT: I have tried to add additional BootstrapperService stateless service and spawn the actors from there in BootstrapperService.RunAsync:

protected override async Task RunAsync(CancellationToken cancellationToken)
{
  await base.RunAsync(cancellationToken);
  await Task.Delay(10000);

  for (int i = 0; i < 10; i++)
  {
    ICustomActor proxy = ActorProxy.Create<ICustomActor>(new ActorId(i));
    await proxy.StartAsync();
  }
}

Nevertheless, the call to proxy.StartAsync() throws the exact same exception as from within the InternalCustomActorService.RunAsync above.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Palo Mraz
  • 625
  • 5
  • 16

1 Answers1

3

Remove the following code from your custom actor service:

     protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() 
 { 
   var remotingListener = new ServiceReplicaListener(context => this.CreateServiceRemotingListener(context)); 
   return new ServiceReplicaListener[] { remotingListener }; 
 } 

This is removing the ActorRemotingListener that the base ActorService is setting up. If you would like to add additional listener, call the base CreateServiceReplicaListeners method, get the listeners and then add custom listener.

VipulM-MSFT
  • 476
  • 3
  • 5
  • Cool, thank you! I was a bit mislead by the information here https://azure.microsoft.com/en-us/documentation/articles/service-fabric-reliable-services-communication-remoting/ : "The `Microsoft.ServiceFabric.Services.Remoting.Runtime` namespace contains an extension method, `CreateServiceRemotingListener` for both stateless **and stateful services** that can be used to create a remoting listener using the default remoting transport protocol." – Palo Mraz Jun 25 '16 at 07:05