Table of Contents

Writing Simple PMI Clients

PMI operations are identified by a string and can be initiated by clients using the Cache.Invoke method.

Prerequisites

  • ScaleOut StateServer Pro license

Procedure

  1. Determine the name of the PMI operation to execute.

    • A handler application hosts the code implementing the PMI operation. Your client will use the same operationId identifier that the handler uses when it registers with the ScaleOut service.
  2. Connect to the ScaleOut service and build a cache.

    • A PMI operation is scoped to the objects in a cache. Use the same cache that the PMI handler app uses when it registers with the ScaleOut service.

    • In this example, the PMI client uses the same cache as the handler in the Writing Simple PMI Handlers topic.

    using System;
    using System.Text;
    using Scaleout.Client;
    
    class Program
    {
        static void Main(string[] args)
        {
            // Connect to the cache that stores login times.
            var conn = GridConnection.Connect("bootstrapGateways=localhost:721");
            var cacheBuilder = new CacheBuilder<string, DateTime>("LoginTimes", conn);
            var cache = cacheBuilder.Build();
    
            // Add some test data to the cache:
            for (int i = 0; i < 50; i++)
            {
                DateTime lastLogin = DateTime.UtcNow - TimeSpan.FromDays(i % 10);
                cache.AddOrUpdate($"User {i}", lastLogin);
            }
    
            // ... continued below
        }
    }
    
  3. Use the Cache.Invoke method to execute the PMI operation on the farm of ScaleOut hosts. The parameters to the invoke operation are:

    • operationId: The name of a registered invocation handler that is running on the ScaleOut farm.
    • param:: A parameter value, serialized to byte array, that can be passed to invocation handlers derived from ForEachWithParam or ReduceWithParam. Use null for PMI operations that do not take a parameter.
    • invokeTimeout: (Optional) The maximum allowed time for the PMI operation to complete. Use null or TimeSpan.Zero to wait indefinitely.
    • invocationGrid: (Optional) If a ScaleOut Invocation Grid is used to deploy/host invocation handler code, its name can be specified here. This sample does not use invocation grids.
    var response = cache.Invoke(operationId: "Find inactive", 
                                param: null, 
                                invokeTimeout: TimeSpan.Zero);
    
  4. Check whether the PMI operation succeeded or failed.

    • If an unhandled exception is thrown from an invocation handler, error data will be sent back and made available to the Invoke client through the ErrorData property. The representation and encoding of the error will vary depending on the library that is used to handle the PMI operation; if the handler is implemented using the Scaleout.Client library, the error will be the full "ToString()" text representation of the exception, encoded as UTF-8.
    if (response.Result == ServerResult.InvokeCompleted)
    {
        Console.WriteLine("PMI operation completed successfully.");
        Console.WriteLine($"{response.SuccessCount} objects were evaluated.");
    }
    else if (response.Result == ServerResult.UnhandledExceptionInCallback)
    {
        Console.WriteLine("Unhandled exception(s) were thrown from invocation handler.");
        string exceptionInfo = Encoding.UTF8.GetString(response.ErrorData);
        Console.WriteLine(exceptionInfo);
    }
    else
    {
        Console.WriteLine($"Cache.Invoke returned unexpected {response.Result}");
    }