docs: function prepareMessagesForSequencing(messages, states, context) {
    if (messages.length < 2) return;
  
    const sequencingRequired = context.streamProcessing.sequencingRequired;
  
    const allSeqNos = messages.map(msg => states.get(msg).seqNos);
  
    // Find the maximum number of sequence number parts across all of the messages' sequence numbers
    const maxParts = allSeqNos.map(e => e.length).reduce((a, b) => Math.max(a, b));
  
    if (!allSeqNos.every(sns => sns.length === maxParts)) {
      context.warn(`NOT all of the messages' sequence numbers have the same number of parts (${maxParts}) - all sequence numbers ${stringify(allSeqNos)}`);
    }
    //const seqNoPartsSortablesByKey = new Array(maxParts);
  
    // Loop through each of the different sequence number parts
    for (let p = 0; p < maxParts; ++p) {
      // Extract all of the messages' keys for the current sequence number part
      const keys = allSeqNos.map(sns => p < sns.length ? sns[p][0] : undefined);
      // const origValues = allSeqNos.map(sns => p < sns.length ? sns[p][1] : undefined);
      const uniqueKeys = uniq(keys);
      // Drop any and all undefined or null keys
      const cleanUniqueKeys = uniqueKeys.filter(k => !!k);
      context.trace(`Seq # part[${p}]: ${cleanUniqueKeys.length} clean of ${uniqueKeys.length} unique of ${keys.length} key${keys.length !== 1 ? 's' : ''} - ${stringify(cleanUniqueKeys)}`);
  
      if (uniqueKeys.length > 1) {
        throwErrorOrWarn(`NOT all of the messages have the same key at sequence number part[${p}]: - keys ${stringify(keys)}; all sequence numbers ${stringify(allSeqNos)}`,
          sequencingRequired, context);
      }
      const sortablesByKey = new Map();
      //seqNoPartsSortablesByKey[p] = sortablesByKey;
  
      for (let k = 0; k < cleanUniqueKeys.length; ++k) {
        const key = cleanUniqueKeys[k];
  
        // Extract all of the messages' values for the current key & sequence number part (using undefined for any different keys' values)
        const values = allSeqNos.map(sns => p < sns.length && sns[p][0] === key ? sns[p][1] : undefined);
  
        // Resolve a sortable (sort type, compare function & sortable values) for the current key and part's values
        const sortable = sorting.toSortable(values, true);
        sortablesByKey.set(key, sortable);
        context.trace(`Seq # part[${p}] & key (${key}): sort type (${sortable.sortType}); sample sortable values ${stringify(sortable.sortableValues.slice(0, 3))}`); // old values ${stringify(origValues)}`);
      }
  
      // Set each of the sortable values on their corresponding message's sequence number part (and attach the old
      // value and sortable information to the part)
      for (let m = 0; m < allSeqNos.length; ++m) {
        const seqNo = allSeqNos[m];
        if (p < seqNo.length) {
          const seqNoPart = seqNo[p];
          const key = seqNoPart[0];
  
          Object.defineProperty(seqNoPart, 'oldValue', {value: seqNoPart[1], writable: true, enumerable: false});
  
          const sortable = sortablesByKey.get(key);
          Object.defineProperty(seqNoPart, 'sortable', {value: sortable, writable: true, enumerable: false});
  
          seqNoPart[1] = sortable ? sortable.sortableValues[m] : undefined;
  
          if (context.traceEnabled && !deepEqual(seqNoPart[1], seqNoPart.oldValue)) {
            context.trace(`Seq # part[${p}] & key (${key}) & message (${m}): sortable value (${stringify(seqNoPart[1])}); old value (${stringify(seqNoPart.oldValue)}); sortable.sortType (${sortable ? sortable.sortType : undefined})`);
          }
        }
      }
    }
    //return seqNoPartsSortablesByKey
  }