com.netflix.dyno.recipes.counter.DynoJedisBatchCounter Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2011 Netflix
*
* Licensed 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.netflix.dyno.recipes.counter;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import com.netflix.dyno.jedis.DynoJedisClient;
import javax.annotation.concurrent.ThreadSafe;
/**
* Batch implementation of {@link DynoCounter} that uses an in-memory counter to
* track {@link #incr()} calls and flushes the value at the given frequency.
*/
@ThreadSafe
public class DynoJedisBatchCounter implements DynoCounter {
private final AtomicBoolean initialized = new AtomicBoolean(false);
private final AtomicLong localCounter;
private final AtomicReference counter = new AtomicReference(null);
private final Long frequencyInMillis;
private final ScheduledExecutorService counterThreadPool = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "DynoJedisBatchCounter-Poller");
}
});
public DynoJedisBatchCounter(String key, DynoJedisClient client, Long frequencyInMillis) {
this.counter.compareAndSet(null, new DynoJedisCounter(key, client));
this.localCounter = new AtomicLong(0L);
this.frequencyInMillis = frequencyInMillis;
}
@Override
public void initialize() {
if (initialized.compareAndSet(false, true)) {
counter.get().initialize();
counterThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
if (localCounter.get() > 0) {
counter.get().incrBy(localCounter.getAndSet(0));
}
}
}, 1000, frequencyInMillis, TimeUnit.MILLISECONDS);
}
}
@Override
public void incr() {
if (!initialized.get()) {
throw new IllegalStateException("Counter has not been initialized");
}
this.localCounter.incrementAndGet();
}
@Override
public void incrBy(long value) {
if (!initialized.get()) {
throw new IllegalStateException("Counter has not been initialized");
}
this.localCounter.addAndGet(value);
}
@Override
public Long get() {
return counter.get().get();
}
@Override
public String getKey() {
return counter.get().getKey();
}
@Override
public List getGeneratedKeys() {
return counter.get().getGeneratedKeys();
}
@Override
public void close() throws Exception {
try {
counterThreadPool.shutdownNow();
} catch (Throwable th) {
// ignore
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy