Remote Counters

What You Will Learn

How to create and use distributed counters: bounded strong counters with upper limits, unbounded strong counters with compare-and-set operations, and weak counters optimized for fast increments.

Prerequisites

  • Java 17+

  • An Infinispan Server running on localhost:11222 (or Docker/Podman available for Testcontainers)

Step 1: Connect and Create a Bounded Strong Counter

Connect to the server, obtain a CounterManager, and define a counter with an upper bound. Attempts to exceed the bound throw an exception:

      // Connect to the server and obtain the CounterManager
      cacheManager = TutorialsConnectorHelper.connect();
      counterManager = RemoteCounterManagerFactory.asCounterManager(cacheManager);

      // Create a bounded strong counter with an upper bound of 10
      counterManager.defineCounter("counter-1", CounterConfiguration.builder(CounterType.BOUNDED_STRONG)
              .upperBound(10)
              .initialValue(1)
              .build());

      // StrongCounter provides the higher consistency. Its value is known during the increment/decrement and it may be bounded.
      // Bounded counters are aimed for uses cases where a limit is needed.
      counter1 = counterManager.getStrongCounter("counter-1");
      // All methods returns a CompletableFuture. So you can do other work while the counter value is being computed.
      counter1.getValue().thenAccept(value -> System.out.println("Counter-1 initial value is " + value)).get();

Step 2: Create an Unbounded Strong Counter

Unbounded strong counters support compare-and-set, listeners, and reset:

      // Similar to counter-1, counter-2 is a strong counter but it is unbounded. It will never throw the CounterOutOfBoundsException
      counterManager.defineCounter("counter-2", CounterConfiguration.builder(CounterType.UNBOUNDED_STRONG)
              .initialValue(2)
              .build());

      counter2 = counterManager.getStrongCounter("counter-2");

      // All counters allow a listener to be registered.
      // The handle can be used to remove the listener
      counter2.addListener(event -> System.out
              .println("Counter-2 event: oldValue=" + event.getOldValue() + " newValue=" + event.getNewValue()));

      // Adding MAX_VALUE won't throws an exception. But the all the increments won't have any effect since we can store
      //any value larger the MAX_VALUE
      counter2.addAndGet(Long.MAX_VALUE).thenAccept(aLong -> System.out.println("Counter-2 value is " + aLong)).get();

      // Conditional operations are allowed in strong counters
      counter2.compareAndSet(Long.MAX_VALUE, 0)
              .thenAccept(aBoolean -> System.out.println("Counter-2 CAS result is " + aBoolean)).get();
      counter2.getValue().thenAccept(value -> System.out.println("Counter-2 value is " + value)).get();

      // Reset the counter to its initial value (2)
      counter2.reset().get();
      counter2.getValue().thenAccept(value -> System.out.println("Counter-2 initial value is " + value)).get();

Step 3: Create a Weak Counter

Weak counters trade consistency for speed. Their value is computed lazily:

      // And finally, the third counter is a weak counter.
      counterManager.defineCounter("counter-3", CounterConfiguration.builder(CounterType.WEAK)
              .initialValue(3)
              .build());

      // Retrieve counter-3
      counter3 = counterManager.getWeakCounter("counter-3");
      // Weak counter doesn't have its value available during updates. This makes the increment faster than the StrongCounter
      // Its value is computed lazily and stored locally.
      // Its main use case is for uses-case where faster increments are needed.
      counter3.add(5).thenAccept(aVoid -> System.out.println("Adding 5 to counter-3 completed!")).get();

      // Check the counter value.
      System.out.println("Counter-3 value is " + counter3.getValue());

Step 4: Run the Tutorial

mvn package exec:java

You should see output showing counter values, bound exceptions, listener events, and compare-and-set results.

What’s Next