Distributed Collections

The atomix-collections module provides a set of asynchronous, distributed collection-like resources. The resources provided by the collections module do not implement JDK collection interfaces because Atomix’s APIs are asynchronous, but their methods are equivalent to their blocking counterparts and can easily be wrapped in blocking collection interfaces.

DistributedMap

The DistributedMap resources provides an asynchronous API similar to that of java.util.Map.

To create a DistributedMap, use the Atomix#getMap(String) method:

atomix.<String, String>getMap("foo-map").thenAccept(map -> {
  // Do something with the map
});

Once the map has been created, the methods closely mimic those of java.util.Map. DistributedMap returns CompletableFuture for all methods:

map.put("foo", "Hello world!").thenRun(() -> {
  map.get("foo").thenAccept(result -> {
    assert result.equals("Hello world!");
  });
});

To block and wait for results instead, call join() or get() on the returned CompletableFutures:

map.put("foo", "Hello world!").join();
assert map.get("foo").join().equals("Hello world!");

Expiring Keys

DistributedMap supports configurable TTLs for map keys. To set a TTL on a key, simply pass a Duration when adding a key to the map:

map.put("foo", "Hello world!", Duration.ofSeconds(1)).thenRun(() -> {
  System.out.println("Key added with TTL");
});

Note that TTL timers are deterministically controlled by the cluster leader and are approximate representations of wall clock time that should not be relied upon for accuracy.

Events

DistributedMap also supports events that indicate when a map has changed:

map.onAdd(event -> {
  System.out.println("Added " + event.entry());
});

map.onRemove(event -> {
  System.out.println("Removed " + event.entry());
});

map.onUpdate(event -> {
  System.out.println("Updated " + event.entry());
});

DistributedMultiMap

The DistributedMultiMap resources provides a map-like API for storing multiple values for each key in a map.

To create a DistributedMultiMap, use the Atomix#getMultiMap(String) method:

atomix.<String, String>getMultiMap("foo-map").thenAccept(map -> {
  // Do something with the multimap
});

Multi-maps store Collections of values rather than single values.

map.put("foo", "Hello world!").join();
map.put("foo", "Hello world again!").join();

Collection<String> values = map.get("foo").join();
assert values.contains("Hello world!");
assert values.contains("Hello world again!");

DistributedSet

The DistributedSet resources provides an asynchronous API similar to that of java.util.Set.

To create a DistributedSet, use the Atomix#getSet(String) method:

atomix.<String>getSet("foo-set").thenAccept(set -> {
  // Do something with the set
});

Once the set has been created, the methods closely mimic those of java.util.Set. DistributedSet returns CompletableFuture for all methods:

set.add("Hello world!").thenRun(() -> {
  set.contains("Hello world!").thenAccept(result -> {
    assert result;
  });
});

Expiring Values

DistributedSet supports configurable TTLs for set values. To set a TTL on a value, simply pass a Duration when adding a value to the set:

set.add("Hello world!", Duration.ofSeconds(1)).thenAccept(succeeded -> {
  // If the add failed, the TTL will not have been set
  if (succeeded) {
    System.out.println("Value added with TTL");
  } else {
    System.out.println("Value add failed");
  }
});

Note that TTL timers are deterministically controlled by the cluster leader and are approximate representations of wall clock time that should not be relied upon for accuracy.

DistributedQueue

The DistributedQueue resources provides an asynchronous API similar to that of java.util.Queue.

To create a DistributedQueue, use the Atomix#getQueue(String) method:

atomix.<String>getQueue("foo-queue").thenAccept(queue -> {
  // Do something with the queue
});

Once the set has been created, the methods closely mimic those of java.util.Queue. DistributedQueue returns CompletableFuture for all methods:

queue.add("Hello world!").thenRun(() -> {
  queue.poll().thenAccept(result -> {
    assert result.equals("Hello world!");
  });
});