Table of Contents

Retrieving Results

If a PMI operation returns a result, the serialized result value can be accessed from the InvokeResponse.ResultObject property as a byte array.

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 Returning Aggregated Results topic.

    using System;
    using Scaleout.Client;
    using System.IO;
    using System.Text;
    
    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.
    • 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: "Get inactive count", 
                                param: null, 
                                invokeTimeout: TimeSpan.Zero);
    
  4. Deserialize the result object if the PMI operation was successful.

    • Result objects must be deserialized in a manner that is compatible with the invocation handler's SerializeResult implementation.

    • 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.

    • The InvokeResponse.ResultObject byte array will be null if no objects were evaluated (for example, if Invoke() is called on an empty cache or if the Invoke call was made on a LINQ expression that filtered out all objects in the cache).

    if (response.Result == ServerResult.InvokeCompleted)
    {
        Console.WriteLine("PMI operation completed successfully.");
        Console.WriteLine($"{response.SuccessCount} objects were evaluated.");
    
        // Deserialize result object:
        if (response.ResultObject != null)
        {
            MemoryStream ms = new MemoryStream(response.ResultObject);
            BinaryReader br = new BinaryReader(ms);
            int inactiveCount = br.ReadInt32();
    
            Console.WriteLine($"{inactiveCount} inactive users were found.");
        }
    }
    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}");
    }