Skip to content

Instantly share code, notes, and snippets.

@fieldju
Created September 24, 2019 20:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fieldju/79147912905dbc1a5c55e624a69c4b81 to your computer and use it in GitHub Desktop.
Save fieldju/79147912905dbc1a5c55e624a69c4b81 to your computer and use it in GitHub Desktop.
package com.nike.cerberus.cache;
import org.apache.ibatis.builder.InitializingObject;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import static com.github.benmanes.caffeine.cache.Caffeine.newBuilder;
/**
* A simple Caffeine backed cache that auto expires items after a certain time period,
* to help us against bursty traffic that does repeat reads.
*/
public class DatabaseCache implements Cache, InitializingObject {
private final Logger log = LoggerFactory.getLogger(getClass());
private com.github.benmanes.caffeine.cache.Cache<Object, Object> delegate;
private final String id;
public DatabaseCache(String id) {
this.id = id;
}
/**
* This method gets called after this class is instantiated by MyBatis and all the properties have been set.
*/
@Override
public void initialize() {
log.info("Database cache with namespace: {} has been initialized", id);
delegate = newBuilder()
.expireAfterWrite(10, TimeUnit.SECONDS)
.build();
}
@Override
public String getId() {
return id;
}
@Override
public void putObject(Object key, Object value) {
if (key == null || value == null) {
return;
}
delegate.put(key, value);
}
@Override
public Object getObject(Object key) {
return delegate.getIfPresent(key);
}
@Override
public Object removeObject(Object key) {
Object res = delegate.getIfPresent(key);
delegate.invalidate(key);
return res;
}
@Override
public void clear() {
// NO-OP, my batis by default clears the entire namespaced cache when a write action occurs,
// we do not want that here, we are expiring the cache / making reads eventually consistent.
// Since we run Cerberus in a cluster anyways and each instance will have it's own generated cache, a simple small
// time window where items purge themselves is adequate.
}
@Override
public int getSize() {
try {
return Math.toIntExact(delegate.estimatedSize());
} catch (ArithmeticException e) {
return Integer.MAX_VALUE;
}
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
@Override
public int hashCode() {
return Objects.hash(delegate, getId());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DatabaseCache)) return false;
DatabaseCache that = (DatabaseCache) o;
return delegate.equals(that.delegate) &&
getId().equals(that.getId());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment