Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#19725 debounces graphql cache evictions and syncronizes the cache re…
…build
- Loading branch information
Showing
3 changed files
with
128 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.dotcms.concurrent; | ||
|
||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.TimeUnit; | ||
import com.dotmarketing.util.Logger; | ||
import com.google.common.annotations.VisibleForTesting; | ||
|
||
/** | ||
* Usage: | ||
* | ||
* final Debouncer debouncer = new Debouncer(); | ||
* debouncer.debounce("myRunnableKey", new Runnable() {()->{runnable..} , 300, TimeUnit.MILLISECONDS); | ||
*/ | ||
public class Debouncer { | ||
|
||
@VisibleForTesting | ||
Debouncer(Long runCount) { | ||
this.runCount = runCount; | ||
} | ||
|
||
public Debouncer() { | ||
|
||
} | ||
|
||
@VisibleForTesting | ||
Long runCount = null; | ||
|
||
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); | ||
private final ConcurrentHashMap<String, Future<?>> delayedMap = new ConcurrentHashMap<>(); | ||
|
||
/** | ||
* Debounces {@code callable} by {@code delay}, i.e., schedules it to be executed after | ||
* {@code delay}, or cancels its execution if the method is called with the same key within the | ||
* {@code delay} again. | ||
*/ | ||
public void debounce(final String key, final Runnable runnable, final long delay, final TimeUnit unit) { | ||
final Future<?> prev = delayedMap.put(key, scheduler.schedule(new Runnable() { | ||
@Override | ||
public void run() { | ||
try { | ||
if (null != runCount) { | ||
++runCount; | ||
Logger.info(Debouncer.class, () -> "Debouncer has run : " + runCount + " times"); | ||
} | ||
Logger.info(Debouncer.class, () -> "Debouncer Runnning : " + key + " after " + delay + " " + unit); | ||
|
||
runnable.run(); | ||
} finally { | ||
delayedMap.remove(key); | ||
} | ||
} | ||
}, delay, unit)); | ||
if (prev != null) { | ||
prev.cancel(true); | ||
} | ||
} | ||
|
||
public void shutdown() { | ||
scheduler.shutdownNow(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
dotCMS/src/test/java/com/dotcms/concurrent/DebouncerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.dotcms.concurrent; | ||
|
||
import static org.junit.Assert.*; | ||
import java.util.concurrent.TimeUnit; | ||
import org.junit.Test; | ||
import com.dotmarketing.util.Logger; | ||
|
||
public class DebouncerTest { | ||
|
||
|
||
|
||
|
||
|
||
@Test | ||
public void test() throws InterruptedException { | ||
Debouncer debouncer = new Debouncer(0L); | ||
|
||
// debounce for 10 seconds | ||
debouncer.debounce("testingKey", ()->{Logger.info("DebouncerTest","running debouncer test" );}, 5, TimeUnit.SECONDS); | ||
debouncer.debounce("testingKey", ()->{Logger.info("DebouncerTest","running debouncer test" );}, 5, TimeUnit.SECONDS); | ||
debouncer.debounce("testingKey", ()->{Logger.info("DebouncerTest","running debouncer test" );}, 5, TimeUnit.SECONDS); | ||
debouncer.debounce("testingKey", ()->{Logger.info("DebouncerTest","running debouncer test" );}, 5, TimeUnit.SECONDS); | ||
debouncer.debounce("testingKey", ()->{Logger.info("DebouncerTest","running debouncer test" );}, 5, TimeUnit.SECONDS); | ||
debouncer.debounce("testingKey", ()->{Logger.info("DebouncerTest","running debouncer test" );}, 5, TimeUnit.SECONDS); | ||
debouncer.debounce("testingKey", ()->{Logger.info("DebouncerTest","running debouncer test" );}, 5, TimeUnit.SECONDS); | ||
|
||
Thread.sleep(7*1000); | ||
|
||
|
||
assertTrue("assert that we have only run once", debouncer.runCount==1); | ||
|
||
|
||
|
||
|
||
|
||
} | ||
|
||
} |