code: public ListenableFuture<SegmentsAndMetadata> publish(
        final TransactionalSegmentPublisher publisher,
        final Committer committer,
        final Collection<String> sequenceNames
    )
    {
      final List<SegmentIdWithShardSpec> theSegments = getSegmentWithStates(sequenceNames)
          .map(SegmentWithState::getSegmentIdentifier)
          .collect(Collectors.toList());
  
      final ListenableFuture<SegmentsAndMetadata> publishFuture = ListenableFutures.transformAsync(
          // useUniquePath=true prevents inconsistencies in segment data when task failures or replicas leads to a second
          // version of a segment with the same identifier containing different data; see DataSegmentPusher.push() docs
          pushInBackground(wrapCommitter(committer), theSegments, true),
          sam -> publishInBackground(
              sam,
              publisher
          )
      );
      return Futures.transform(
          publishFuture,
          (Function<? super SegmentsAndMetadata, ? extends SegmentsAndMetadata>) sam -> {
            synchronized (segments) {
              sequenceNames.forEach(segments::remove);
            }
            return sam;
          }
      );
    }
docs: Execute a task in background to publish all segments corresponding to the given sequence names.  The task
  internally pushes the segments to the deep storage first, and then publishes the metadata to the metadata storage.
  
  @param publisher     segment publisher
  @param committer     committer
  @param sequenceNames a collection of sequence names to be published
  
  @return a {@link ListenableFuture} for the submitted task which removes published {@code sequenceNames} from
  {@code activeSegments} and {@code publishPendingSegments}