Skip to content

Commit

Permalink
test(s3stream/util): test FutureTicker (#859)
Browse files Browse the repository at this point in the history
Signed-off-by: Ning Yu <[email protected]>
  • Loading branch information
Chillax-0v0 authored Dec 28, 2023
1 parent 18ff310 commit 99ba37c
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 2 deletions.
29 changes: 27 additions & 2 deletions s3stream/src/main/java/com/automq/stream/utils/FutureTicker.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,48 @@
import java.util.concurrent.TimeUnit;

/**
* A ticker base on {@link CompletableFuture}
* TODO more docs and tests
* A ticker base on {@link CompletableFuture}. It is used to batch operations.
* <p>
* For example, if we want to batch operations every 100ms, we can use the following code:
* <pre>
* {@code
* FutureTicker ticker = new FutureTicker(100, TimeUnit.MILLISECONDS, executor);
* while (true) {
* ticker.tick().thenAccept(v -> operation());
* Thread.sleep(1);
* }
* }
* </pre>
* Operations will be batched every 100ms.
*/
public class FutureTicker {

private final Executor delayedExecutor;

private CompletableFuture<Void> currentTick = CompletableFuture.completedFuture(null);

/**
* Create a ticker with a delay and a executor
* @param delay the delay
* @param unit the time unit of the delay
* @param executor the executor, the {@link CompletableFuture} returned by {@link #tick()} will be completed by this executor
*/
public FutureTicker(long delay, TimeUnit unit, Executor executor) {
this.delayedExecutor = CompletableFuture.delayedExecutor(delay, unit, executor);
}

/**
* Tick the ticker. It returns a future which will complete after the delay.
* If the ticker is already ticking, the same future will be returned.
* It is thread safe to call this method.
*/
public CompletableFuture<Void> tick() {
return maybeNextTick();
}

/**
* Generate a new tick if the current tick is done
*/
private synchronized CompletableFuture<Void> maybeNextTick() {
if (currentTick.isDone()) {
// a future which will complete after delay
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.automq.stream.utils;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertSame;

class FutureTickerTest {

private FutureTicker ticker = new FutureTicker(10, TimeUnit.MILLISECONDS, Executors.newSingleThreadExecutor());

@BeforeEach
void setUp() {
ticker = new FutureTicker(10, TimeUnit.MILLISECONDS, Executors.newSingleThreadExecutor());
}

@Test
void testFirstTick() {
CompletableFuture<Void> tick = ticker.tick();
assertNotNull(tick);
assertFalse(tick.isDone());
}

@Test
void testTwoTicks() {
CompletableFuture<Void> tick1 = ticker.tick();
CompletableFuture<Void> tick2 = ticker.tick();
assertSame(tick1, tick2);
}

@Test
void testDelay() throws InterruptedException {
CompletableFuture<Void> tick1 = ticker.tick();
Thread.sleep(20);
CompletableFuture<Void> tick2 = ticker.tick();
assertFalse(tick2.isDone());
assertNotSame(tick1, tick2);
}
}

0 comments on commit 99ba37c

Please sign in to comment.