docs: public CompletableFuture<Void> startDeduplicationDaemon() {
          stopDaemon = false;
          CompletableFuture<Void> daemon = CompletableFuture.supplyAsync(() -> {
              LOG.info("startDeduplicationDaemon() - attribute de-duplicator daemon started.");
              while (!stopDaemon) {
                  try {
                      List<Attribute> attributes = queue.read(QUEUE_GET_BATCH_MAX);
  
                      LOG.trace("starting a new batch to process these new attributes: {}", attributes);
  
                      // group the attributes into a set of unique (keyspace -> value) pair
                      Set<KeyspaceIndexPair> uniqueKeyValuePairs = attributes.stream()
                              .map(attr -> KeyspaceIndexPair.create(attr.keyspace(), attr.index()))
                              .collect(Collectors.toSet());
  
                      // perform deduplicate for each (keyspace -> value)
                      for (KeyspaceIndexPair keyspaceIndexPair : uniqueKeyValuePairs) {
                          deduplicate(sessionFactory, keyspaceIndexPair);
                      }
  
                      LOG.trace("new attributes processed.");
  
                      queue.ack(attributes);
                  }
                  catch (InterruptedException | RuntimeException e) {
                      LOG.error("An exception has occurred in the attribute de-duplicator daemon. ", e);
                  }
              }
              LOG.info("startDeduplicationDaemon() - attribute de-duplicator daemon stopped");
              return null;
          }, executorServiceForDaemon);
  
          daemon.exceptionally(e -> {
              LOG.error("An unhandled exception has occurred in the attribute de-duplicator daemon. ", e);
              return null;
          });
  
          return daemon;
      }