docs: static Deferred<byte[]> rowKeyTemplateAsync(final TSDB tsdb,
        final String metric, final Map<String, String> tags) {
      final short metric_width = tsdb.metrics.width();
      final short tag_name_width = tsdb.tag_names.width();
      final short tag_value_width = tsdb.tag_values.width();
      final short num_tags = (short) tags.size();
  
      int row_size = (Const.SALT_WIDTH() + metric_width + Const.TIMESTAMP_BYTES 
          + tag_name_width * num_tags + tag_value_width * num_tags);
      final byte[] row = new byte[row_size];
  
      // Lookup or create the metric ID.
      final Deferred<byte[]> metric_id;
      if (tsdb.config.auto_metric()) {
        metric_id = tsdb.metrics.getOrCreateIdAsync(metric, metric, tags);
      } else {
        metric_id = tsdb.metrics.getIdAsync(metric);
      }
  
      // Copy the metric ID at the beginning of the row key.
      class CopyMetricInRowKeyCB implements Callback<byte[], byte[]> {
        public byte[] call(final byte[] metricid) {
          copyInRowKey(row, (short) Const.SALT_WIDTH(), metricid);
          return row;
        }
      }
  
      // Copy the tag IDs in the row key.
      class CopyTagsInRowKeyCB implements
          Callback<Deferred<byte[]>, ArrayList<byte[]>> {
        public Deferred<byte[]> call(final ArrayList<byte[]> tags) {
          short pos = (short) (Const.SALT_WIDTH() + metric_width);
          pos += Const.TIMESTAMP_BYTES;
          for (final byte[] tag : tags) {
            copyInRowKey(row, pos, tag);
            pos += tag.length;
          }
          // Once we've resolved all the tags, schedule the copy of the metric
          // ID and return the row key we produced.
          return metric_id.addCallback(new CopyMetricInRowKeyCB());
        }
      }
  
      // Kick off the resolution of all tags.
      return Tags.resolveOrCreateAllAsync(tsdb, metric, tags)
          .addCallbackDeferring(new CopyTagsInRowKeyCB());
    }