@Override
  public void request(final long n) {
    Preconditions.checkArgument(n == 1, "number of requested items must be 1");

    if (needsSchema) {
      if (schema != null) {
        subscriber.onSchema(schema);
      }
      needsSchema = false;
    }
    // check status since request() can be reentrant through subscriber.onNext()
    // this is to prevent another thread from calling onNext again
    // while the first one is draining and closing the subscription after having called onNext
    // with the last element polled from the queue after being marked done.
    if (!draining) {
      future = exec.submit(() -> {

        if (done) {
          draining = true;
        }
        final T item = poll();
        if (item == null) {
          if (!draining) {
            future = exec.schedule(() -> request(1), BACKOFF_DELAY_MS, TimeUnit.MILLISECONDS);
          }
        } else {
          subscriber.onNext(item);
        }
        if (draining) {
          close();
          if (exception != null) {
            subscriber.onError(exception);
          } else {
            subscriber.onComplete();
          }
        }
      });
    }
  }
@Test(expected = IllegalArgumentException.class)
  public void testExpectsNEqualsOne() {
    final TestSubscriber<String> testSubscriber = new TestSubscriber<String>() {
      @Override
      public void onSubscribe(final Subscription subscription) {
        subscription.request(2);
      }
    };
    final TestPublisher testPublisher = new TestPublisher();
    testPublisher.subscribe(testSubscriber);
  }