package tc.oc.api.model; import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Provider; import java.time.Duration; import tc.oc.api.docs.virtual.PartialModel; import tc.oc.api.message.types.UpdateMultiRequest; import tc.oc.commons.core.scheduler.DebouncedTask; import tc.oc.commons.core.scheduler.Scheduler; public class BatchUpdaterFactory<T extends PartialModel> { private final UpdateService<T> service; private final Provider<BatchUpdateRequest> updateProvider; private final Scheduler scheduler; @Inject BatchUpdaterFactory(UpdateService<T> service, Provider<BatchUpdateRequest> updateProvider, Scheduler scheduler) { this.service = service; this.updateProvider = updateProvider; this.scheduler = scheduler; } public BatchUpdater<T> createBatchUpdater() { return createBatchUpdater(Duration.ZERO); } public BatchUpdater<T> createBatchUpdater(Duration delay) { return new BatchUpdaterImpl(delay); } private class BatchUpdaterImpl implements BatchUpdater<T> { final DebouncedTask task; @Nullable BatchUpdateRequest<T> batchUpdate; BatchUpdaterImpl(Duration delay) { this.task = scheduler.createDebouncedTask(delay, this::flush); } @Override public void flush() { if(batchUpdate != null) { final BatchUpdateRequest<T> batchUpdate = this.batchUpdate; this.batchUpdate = null; task.cancel(); service.updateMulti((UpdateMultiRequest) batchUpdate); } } @Override public void schedule() { task.schedule(); } @Override public void update(T doc) { if(batchUpdate == null) { batchUpdate = updateProvider.get(); } batchUpdate.add(doc); schedule(); } } }