private static WALKeyImpl doFullMarkerAppendTransaction(final WAL wal,
    final NavigableMap<byte[], Integer> replicationScope, final RegionInfo hri, final WALEdit edit,
    final MultiVersionConcurrencyControl mvcc, final Map<String, byte[]> extendedAttributes,
    final boolean sync, final RegionReplicationSink sink) throws IOException {
    // TODO: Pass in current time to use?
    WALKeyImpl walKey = createWALKey(hri, mvcc, replicationScope, extendedAttributes);
    long trx = MultiVersionConcurrencyControl.NONE;
    try {
      trx = wal.appendMarker(hri, walKey, edit);
      WriteEntry writeEntry = walKey.getWriteEntry();
      if (sink != null) {
        writeEntry.attachCompletionAction(() -> sink.add(walKey, edit,
          RpcServer.getCurrentServerCallWithCellScanner().orElse(null)));
      }
      if (sync) {
        wal.sync(trx);
      }
      // Call complete only here because these are markers only. They are not for clients to read.
      mvcc.complete(writeEntry);
    } catch (IOException ioe) {
      if (walKey.getWriteEntry() != null) {
        mvcc.complete(walKey.getWriteEntry());
      }
      /**
       * Here we do not abort the RegionServer for {@link WALSyncTimeoutIOException} as
       * {@link HRegion#doWALAppend} does,because WAL Marker just records the internal state and
       * seems it is no need to always abort the RegionServer when {@link WAL#sync} timeout,it is
       * the internal state transition that determines whether RegionServer is aborted or not.
       */
      throw ioe;
    }
    return walKey;
  }
A 'full' WAL transaction involves starting an mvcc transaction followed by an append, an
optional sync, and then a call to complete the mvcc transaction. This method does it all. Good
for case of adding a single edit or marker to the WAL.
<p/>
This write is for internal use only. Not for external client consumption.
@return WALKeyImpl that was added to the WAL.
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALUtil.java