What's new in Apache Ignite.NET 2.14

Apache Ignite 2.14 has been released. .NET updates include Service Interceptors and Thin Client Data Structures.

Service Interceptors (Middleware)

Ignite Services API provides a powerful mechanism for implementing distributed service-oriented applications. Those applications typically need to deal with a number of cross-cutting concerns, such as logging, monitoring, authentication/authorization, validation, and so on.

Adding the same logging and monitoring code to every service method is tedious and error-prone. Service Interceptors are designed to solve this. We took inspiration from ASP.NET Core Middleware and gRPC Interceptors to create IServiceCallInterceptor API, which provides full control over service method execution.

You can add logic before and after the actual method, handle exceptions, or skip the method call completely:

class MyInterceptor : IServiceCallInterceptor
{
    public object Invoke(string mtd, object[] args, IServiceContext ctx, Func<object> next)
    {
        Console.WriteLine($"Before {mtd}");

        try
        {
            // Invoke the next interceptor in the chain, or the actual method.
            var res = next.Invoke();
            Console.WriteLine($"{mtd} returned {res}");
            return res;
        }
        catch (Exception e)
        {
            Console.WriteLine($"Exception {e} in {mtd}");
            throw;
        }
        finally
        {
            Console.WriteLine($"After {mtd}");
        }
    }
}

You can have as many interceptors as you like. Simply add them to ServiceConfiguration.Interceptors.

More details:

Distributed Data Structures in Thin Client

Data structures are coming to thin clients! Java and .NET clients now have access to AtomicLong and IgniteSet.

AtomicLong

Cluster-wide thread-safe number. Can be used as an ID generator, counter, and so on. All nodes see the same value and can perform updates atomically.

IAtomicLongClient atomicLong = Client.GetAtomicLong(
    name: "my-id", initialValue: 1, create: true);

Assert.AreEqual(2, atomicLong.Increment());
Assert.AreEqual(2, atomicLong.Read());

Assert.AreEqual(1, atomicLong.Decrement());
Assert.AreEqual(1, atomicLong.Read());

Assert.AreEqual(101, atomicLong.Add(100));
Assert.AreEqual(101, atomicLong.Read());

Assert.AreEqual(101, atomicLong.CompareExchange(3, 2));
Assert.AreEqual(101, atomicLong.Read());

Assert.AreEqual(101, atomicLong.CompareExchange(4, 101));
Assert.AreEqual(4, atomicLong.Read());

CompareExchange in Ignite atomic long has the same semantics as Interlocked.CompareExchange in the .NET library.

IgniteSet

Similar to HashSet<T>, but distributed and visible to all cluster nodes. Implements ISet<T>.

IIgniteSetClient<int> set = Client.GetIgniteSet<int>(
    name: "my-set", new CollectionClientConfiguration());

set.Add(1);
set.Add(2);
set.Remove(1);

Assert.IsTrue(set.Contains(2));
Assert.IsFalse(set.Contains(1));

More details:

Links

Written on October 12, 2022