-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrong behavior of buffer( timespan, count ) ? #756
Comments
Ok, the marble diagram was updated, but it still does not work.
Output:
|
Can you refactor that as a unit test with necessary assertions so it can go inside https://github.com/Netflix/RxJava/blob/master/rxjava-core/src/test/java/rx/operators/OperationBufferTest.java ? |
Unit tests provided by @Acardiac in #761 demonstrating the issue: @Test
public void bufferTimeSpanEmitAllItems() throws InterruptedException {
final int maxRounds = 100;
final int maxCount = 1000;
final int bufferTimeSpan = 42; // µs
int round = 0;
final AtomicInteger count = new AtomicInteger(0);
do {
++round;
count.set(0);
Observable<List<Integer>> observable = Observable //
.range(1, maxCount) //
.buffer(bufferTimeSpan, TimeUnit.MICROSECONDS);
final CountDownLatch lock = new CountDownLatch(1);
observable.subscribe( // onNext
new Action1<List<Integer>>() {
@Override
public void call(List<Integer> val) {
count.addAndGet(val.size());
}
}, // onError
new Action1<Throwable>() {
@Override
public void call(Throwable err) {
lock.countDown();
}
}, // onComplete
new Action0() {
@Override
public void call() {
lock.countDown();
}
}
);
lock.await();
} while ((maxCount == count.get()) && (round < maxRounds));
assertEquals(maxCount, count.get());
assertEquals(maxRounds, round);
}
@Test
public void bufferCountEmitAllItems() throws InterruptedException {
final int maxRounds = 100;
final int maxCount = 1000;
final int bufferCount = 42;
int round = 0;
final AtomicInteger count = new AtomicInteger(0);
do {
++round;
count.set(0);
Observable<List<Integer>> observable = Observable //
.range(1, maxCount) //
.buffer(bufferCount);
final CountDownLatch lock = new CountDownLatch(1);
observable.subscribe( // onNext
new Action1<List<Integer>>() {
@Override
public void call(List<Integer> val) {
count.addAndGet(val.size());
}
}, // onError
new Action1<Throwable>() {
@Override
public void call(Throwable err) {
lock.countDown();
}
}, // onComplete
new Action0() {
@Override
public void call() {
lock.countDown();
}
}
);
lock.await();
} while ((maxCount == count.get()) && (round < maxRounds));
assertEquals(maxCount, count.get());
assertEquals(maxRounds, round);
} |
The rewritten exact buffer with count+timespan creates a new buffer if either count or timespan is reached. The inexact-timed version emits the full buffer but does not start a new window until the timespan ellapses. Do we need to ensure no values are left out? |
Both of those unit tests are passing for me (v0.18.3+) now whereas at least 1 of them was failing still as of 0.17.6. |
According to the marble diagram, in case the buffer is full, all subsequent items are ignored till time interval has elapsed.
(green item -> https://github.com/Netflix/RxJava/wiki/Transforming-Observables#buffer )
But according to the description:
imho the timespan timer as well as counter should be restarted immediately after buffer emission, so none of the items are dropped.
Compare to Lee Campbell:
http://www.introtorx.com/Content/v1.0.10621.0/13_TimeShiftedSequences.html#Buffer
see also:
http://msdn.microsoft.com/en-us/library/hh229200.aspx
Bug or feature?
The text was updated successfully, but these errors were encountered: