Запускать функцию (например, очистку) только один раз после нескольких POST / DELETEs / PUTs - PullRequest
0 голосов
/ 02 мая 2019

Трафик на моем сайте может стать интенсивным, и я хотел бы снизить частоту запуска дорогой функции очистки;Я также хотел бы запустить его в фоновом режиме.

Я реализовал кэш с помощью RemovalListener и ожидал, что он будет работать асинхронно через 30 секунд после создания записи, но я вижу, что он либо не запускается вообще, либо запускается мгновенно.Мне также приходится ждать сценария очистки, когда он все-таки запускается.Я неправильно понимаю цель прослушивания кэша и удаления?

@Path("my-endpoint")
public class MyResource{

    private static final Cache<String, String> debounceCleaner = CacheBuilder
        .newBuilder()
        .maximumSize(1000)
        .expireAfterWrite(30, TimeUnit.SECONDS)
        .removalListener((RemovalListener<String, String>) x-> new Cleaner().clean())
        .build();

    @PUT
    public Response update(){
        ...

        try{
            debounceCleaner.get("foo", ()->"bar");
        } catch (ExecutionException ex){
            throw new IllegalStateException("Unhandled", ex);
        }

        return Response(...)

1 Ответ

0 голосов
/ 03 мая 2019

Срок действия кэша не предназначен для использования в качестве средства удаления ошибок.Другие вопросы ответили, как создать разборщик в разной степени.

реализация debounce в Java Немедленно доставить первый элемент, debounce: следующие элементы

Я написал debouncer для этого приложения следующим образом:

public class Debouncer {

    private final int TIMEOUT = 30000;
    private Runnable runnable;
    private Thread backgroundRunnerLoop;
    private Date lastRun = null;
    private Date lastRequest = null;

    public Debouncer(Runnable runnable) {
        this.runnable = runnable;
        this.backgroundRunnerLoop = new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(TIMEOUT);
                    if (lastRequest != null && (lastRun == null || lastRun.before(DateUtils.addMilliseconds(lastRequest, TIMEOUT)))) {
                        this.runnable.run();
                        lastRun = new Date();
                    }
                } catch (Exception ex) {
                    throw new IllegalStateException("Debouncer loop broke.", ex);
                }
            }
        });
    }

    public void start() {
        if(!backgroundRunnerLoop.isAlive()){
            backgroundRunnerLoop.start();
        }
    }

    public void resetTimer() {
        lastRequest = new Date();
    }
}

Я создаю это так

@Path("my-endpoint")
public class MyResource {
    private static final Debouncer debouncer = new Debouncer(() -> new Cleaner().run());

    public MyResource() {
        debouncer.start();
    }

    @PUT
    public Response update(){
        // ...
        debouncer.resetTimer();

        return Response.noContent(...).build();
    }
}
...