4
votes

My situation:

Problem:

I'm trying to change the communication between my Stateful Service and my Stateless WebAPI from RPC to HTTP Communication because I want to avoid using an interface to communicate between the services. Is this even possible with HTTP Communication? If so, how can my stateless WebAPI call specific methods in my Stateful application without using an interface?

UPDATE:

Thanks to alltej, I started reading up more on HttpCommunicationListeners. This tutorial (https://docs.microsoft.com/nl-nl/azure/service-fabric/service-fabric-concepts-partitioning) explained Http Communication pretty well.

In the code snippet below: "CreateServiceReplicaListeners()" calls CreateInternalListener() which then calls "ProcessInternalRequest()" which then finally calls "AddUserAsync()".

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

    private ICommunicationListener CreateInternalListener(ServiceContext context)
    {
        EndpointResourceDescription internalEndpoint = context.CodePackageActivationContext.GetEndpoint("ProcessingServiceEndpoint");

        string uriPrefix = String.Format(
            "{0}://+:{1}/{2}/{3}-{4}/",
            internalEndpoint.Protocol,
            internalEndpoint.Port,
            context.PartitionId,
            context.ReplicaOrInstanceId,
            Guid.NewGuid());

        string nodeIP = FabricRuntime.GetNodeContext().IPAddressOrFQDN;

        string uriPublished = uriPrefix.Replace("+", nodeIP);
        return new HttpCommunicationListener(uriPrefix, uriPublished, this.ProcessInternalRequest);
    }

    private async Task ProcessInternalRequest(HttpListenerContext context, CancellationToken cancelRequest)
    {
        string output = null;
        string user = context.Request.QueryString["lastname"].ToString();

        try
        {
            output = await this.AddUserAsync(user);
        }
        catch (Exception ex)
        {
            output = ex.Message;
        }

        using (HttpListenerResponse response = context.Response)
        {
            if (output != null)
            {
                byte[] outBytes = Encoding.UTF8.GetBytes(output);
                response.OutputStream.Write(outBytes, 0, outBytes.Length);
            }
        }
    }

    private async Task<string> AddUserAsync(string user)
    {
        IReliableDictionary<String, String> dictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<String, String>>("dictionary");

        using (ITransaction tx = this.StateManager.CreateTransaction())
        {
            bool addResult = await dictionary.TryAddAsync(tx, user.ToUpperInvariant(), user);

            await tx.CommitAsync();

            return String.Format(
                "User {0} {1}",
                user,
                addResult ? "sucessfully added" : "already exists");
        }
    }
}
1

1 Answers

3
votes

MyCustomHttpListener is a class that you have to create as your own custom listener that implements the ICommunicationListener. It contains the three methods you need to override. See example here for an OwinCommunicationListener: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-webapi