code: public final Flux<List<T>> buffer(Duration bufferingTimespan, Duration openBufferEvery, Scheduler timer) {
  		if (bufferingTimespan.equals(openBufferEvery)) {
  			return buffer(bufferingTimespan, timer);
  		}
  		return bufferWhen(interval(Duration.ZERO, openBufferEvery, timer), aLong -> Mono
  				.delay(bufferingTimespan, timer));
  	}
docs: Collect incoming values into multiple {@link List} buffers created at a given
  {@code openBufferEvery} period, as measured on the provided {@link Scheduler}. Each
  buffer will last until the {@code bufferingTimespan} has elapsed (also measured on the scheduler),
  thus emitting the bucket in the resulting {@link Flux}.
  <p>
  When bufferingTimespan < openBufferEvery : dropping buffers
  <p>
  <img class="marble" src="doc-files/marbles/bufferWithTimespanLessThanOpenBufferEvery.svg" alt="">
  <p>
  When bufferingTimespan > openBufferEvery : overlapping buffers
  <p>
  <img class="marble" src="doc-files/marbles/bufferWithTimespanGreaterThanOpenBufferEvery.svg" alt="">
  <p>
  When bufferingTimespan == openBufferEvery : exact buffers
  <p>
  <img class="marble" src="doc-files/marbles/bufferWithTimespanEqualsOpenBufferEvery.svg" alt="">
  
  @reactor.discard This operator discards the currently open buffer upon cancellation or error triggered by a data signal.
  It DOES NOT provide strong guarantees in the case of overlapping buffers, as elements
  might get discarded too early (from the first of two overlapping buffers for instance).
  
  @param bufferingTimespan the duration from buffer creation until a buffer is closed and emitted
  @param openBufferEvery the interval at which to create a new buffer
  @param timer a time-capable {@link Scheduler} instance to run on
  
  @return a microbatched {@link Flux} of {@link List} delimited by the given period openBufferEvery and sized by bufferingTimespan