Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ls.ni.networkfilter.common.cache.types.NoopCache;
import ls.ni.networkfilter.common.cache.types.RedisCache;
import ls.ni.networkfilter.common.config.Config;
import ls.ni.networkfilter.common.config.cache.types.RedisSentineledCacheSettings;
import org.jetbrains.annotations.NotNull;

import java.time.Duration;
Expand All @@ -25,6 +26,19 @@ yield new RedisCache(
Duration.ofMinutes(config.getCaches().getRedis().getCacheTimeMinutes())
);
}
case REDIS_SENTINELED -> {
RedisSentineledCacheSettings cacheSettings = config.getCaches().getSentinel();
yield new RedisCache(
cacheSettings.getMaster(),
cacheSettings.getAddresses(),
cacheSettings.getUsername(),
cacheSettings.getPassword(),
cacheSettings.isSsl(),
cacheSettings.getUsername(),
cacheSettings.getPassword(),
Duration.ofMinutes(cacheSettings.getCacheTimeMinutes())
);
}
default -> throw new IllegalStateException("Cache '" + config.getCache() + "' is not supported!");
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,84 @@
import ls.ni.networkfilter.common.filter.FilterResult;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.*;

import java.time.Duration;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

public class RedisCache implements Cache {

private final ObjectMapper objectMapper = new ObjectMapper();

private final JedisPool jedisPool;
private final UnifiedJedis unifiedJedis;
private boolean sentineled = false;
private final Duration expireAfterWrite;

private static final int SENTINEL_DEFAULT_PORT = 26379;

public RedisCache(@NotNull String uri, @NotNull Duration expireAfterWrite) {
this.jedisPool = new JedisPool(uri);
this.unifiedJedis = new JedisPooled(uri);

this.expireAfterWrite = expireAfterWrite;

// Close the JedisPool when the JVM is shutting down
Runtime.getRuntime().addShutdownHook(new Thread(this.jedisPool::close));
Runtime.getRuntime().addShutdownHook(new Thread(this.unifiedJedis::close));
}

public RedisCache(String masterName, List<String> sentinelAddresses, String username, String password,
boolean ssl, String sentinelUsername, String sentinelPassword, Duration expireAfterWrite){

this.expireAfterWrite = expireAfterWrite;

Set<HostAndPort> sentinels = sentinelAddresses.stream()
.map(addr -> parseAddress(addr))
.collect(Collectors.toSet());

this.unifiedJedis = new JedisSentineled(masterName, jedisConfig(username, password, ssl),
sentinels, jedisConfig(sentinelUsername, sentinelPassword, ssl));

this.sentineled = true;
}

private static HostAndPort parseAddress(String address) {
return parseAddress(address, SENTINEL_DEFAULT_PORT);
}

private static HostAndPort parseAddress(@NotNull String address, int defaultPort) {
if(address.lastIndexOf(':') > 0){
return HostAndPort.from(address);
}

return new HostAndPort(address, defaultPort);
}

private static JedisClientConfig jedisConfig(String username, String password, boolean ssl) {
return DefaultJedisClientConfig.builder()
.user(username)
.password(password)
.ssl(ssl)
.timeoutMillis(Protocol.DEFAULT_TIMEOUT)
.build();
}

@Override
public @NotNull String getName() {
return "redis";

return sentineled ? "redis_sentineled" : "redis";
}

@Override
public @Nullable FilterResult getIfPresent(@NotNull String key) {
String cacheKey = this.cacheKey(key);

try (Jedis resource = this.jedisPool.getResource()) {
if (!resource.exists(cacheKey)) {
try {
if (!this.unifiedJedis.exists(cacheKey)) {
return null;
}

return this.objectMapper.readValue(resource.get(cacheKey), FilterResult.class);
return this.objectMapper.readValue(this.unifiedJedis.get(cacheKey), FilterResult.class);
} catch (Throwable cause) {
throw new RuntimeException("Failed to get value from Redis", cause);
}
Expand All @@ -64,10 +105,11 @@ public RedisCache(@NotNull String uri, @NotNull Duration expireAfterWrite) {
public void put(@NotNull String key, @NotNull FilterResult value) {
String cacheKey = this.cacheKey(key);

try (Jedis resource = this.jedisPool.getResource()) {
try {
String mappedValue = this.objectMapper.writeValueAsString(value);

resource.setex(cacheKey, (int) this.expireAfterWrite.getSeconds(), mappedValue);
this.unifiedJedis.setex(cacheKey, (int) this.expireAfterWrite.getSeconds(), mappedValue);

} catch (Throwable cause) {
throw new RuntimeException("Failed to put value to Redis", cause);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import ls.ni.networkfilter.common.config.cache.types.DisabledCacheSettings;
import ls.ni.networkfilter.common.config.cache.types.LocalCacheSettings;
import ls.ni.networkfilter.common.config.cache.types.RedisCacheSettings;
import ls.ni.networkfilter.common.config.cache.types.RedisSentineledCacheSettings;

@Data
@NoArgsConstructor
Expand All @@ -26,4 +27,8 @@ public class CacheSettings {
@NotNull
private RedisCacheSettings redis;

@Valid
@NotNull
private RedisSentineledCacheSettings sentinel;

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public enum CacheType {
DISABLED("disabled"),
LOCAL("local"),
REDIS("redis"),
REDIS_SENTINELED("redis_sentineled")
;

private final String key;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ls.ni.networkfilter.common.config.cache.types;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class RedisSentineledCacheSettings {

@NotNull
private String master;

private List<String> addresses;

private String username;
private String password;

@NotNull
@Positive
private Long cacheTimeMinutes;

@NotNull
private boolean ssl;
}
10 changes: 10 additions & 0 deletions common/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ caches:
uri: "redis://user:password@localhost:6379"
cacheTimeMinutes: 15

sentinel:
master: mymaster
addresses:
- localhost:26379
username: ''
password: ''
cacheTimeMinutes: 15
ssl: false


services:
# https://nf.ni.ls
networkfilter:
Expand Down
Loading