diff --git a/pom.xml b/pom.xml index a69d7eb46..1e27719c5 100644 --- a/pom.xml +++ b/pom.xml @@ -86,11 +86,6 @@ gcm-server 1.0.2 - - net.spy - spymemcached - 2.10.1 - com.notnoop.apns apns diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index df4027c63..cc3e98198 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -17,11 +17,10 @@ package org.whispersystems.textsecuregcm; import com.fasterxml.jackson.annotation.JsonProperty; -import org.whispersystems.textsecuregcm.configuration.DirectoryConfiguration; +import org.whispersystems.textsecuregcm.configuration.RedisConfiguration; import org.whispersystems.textsecuregcm.configuration.FederationConfiguration; import org.whispersystems.textsecuregcm.configuration.GraphiteConfiguration; import org.whispersystems.textsecuregcm.configuration.MemcacheConfiguration; -import org.whispersystems.textsecuregcm.configuration.MessageStoreConfiguration; import org.whispersystems.textsecuregcm.configuration.NexmoConfiguration; import org.whispersystems.textsecuregcm.configuration.PushConfiguration; import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration; @@ -60,12 +59,12 @@ public class WhisperServerConfiguration extends Configuration { @NotNull @Valid @JsonProperty - private MemcacheConfiguration memcache; + private RedisConfiguration cache; @NotNull @Valid @JsonProperty - private DirectoryConfiguration directory; + private RedisConfiguration directory; @Valid @NotNull @@ -128,11 +127,11 @@ public class WhisperServerConfiguration extends Configuration { return s3; } - public MemcacheConfiguration getMemcacheConfiguration() { - return memcache; + public RedisConfiguration getCacheConfiguration() { + return cache; } - public DirectoryConfiguration getDirectoryConfiguration() { + public RedisConfiguration getDirectoryConfiguration() { return directory; } diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 1efca0b12..e8840753b 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -21,7 +21,6 @@ import com.codahale.metrics.graphite.GraphiteReporter; import com.fasterxml.jackson.databind.DeserializationFeature; import com.google.common.base.Optional; import com.sun.jersey.api.client.Client; -import net.spy.memcached.MemcachedClient; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.eclipse.jetty.servlets.CrossOriginFilter; import org.skife.jdbi.v2.DBI; @@ -44,14 +43,13 @@ import org.whispersystems.textsecuregcm.controllers.ReceiptController; import org.whispersystems.textsecuregcm.federation.FederatedClientManager; import org.whispersystems.textsecuregcm.federation.FederatedPeer; import org.whispersystems.textsecuregcm.limits.RateLimiters; +import org.whispersystems.textsecuregcm.liquibase.NameableMigrationsBundle; import org.whispersystems.textsecuregcm.mappers.IOExceptionMapper; import org.whispersystems.textsecuregcm.mappers.RateLimitExceededExceptionMapper; import org.whispersystems.textsecuregcm.metrics.CpuUsageGauge; import org.whispersystems.textsecuregcm.metrics.FreeMemoryGauge; import org.whispersystems.textsecuregcm.metrics.NetworkReceivedGauge; import org.whispersystems.textsecuregcm.metrics.NetworkSentGauge; -import org.whispersystems.textsecuregcm.providers.MemcacheHealthCheck; -import org.whispersystems.textsecuregcm.providers.MemcachedClientFactory; import org.whispersystems.textsecuregcm.providers.RedisClientFactory; import org.whispersystems.textsecuregcm.providers.RedisHealthCheck; import org.whispersystems.textsecuregcm.providers.TimeProvider; @@ -80,7 +78,6 @@ import org.whispersystems.textsecuregcm.websocket.AuthenticatedConnectListener; import org.whispersystems.textsecuregcm.websocket.ProvisioningConnectListener; import org.whispersystems.textsecuregcm.websocket.WebSocketAccountAuthenticator; import org.whispersystems.textsecuregcm.workers.DirectoryCommand; -import org.whispersystems.textsecuregcm.liquibase.NameableMigrationsBundle; import org.whispersystems.textsecuregcm.workers.VacuumCommand; import org.whispersystems.websocket.WebSocketResourceProviderFactory; import org.whispersystems.websocket.setup.WebSocketEnvironment; @@ -149,22 +146,22 @@ public class WhisperServerService extends Application nexmoSmsSender = initializeNexmoSmsSender(config.getNexmoConfiguration()); @@ -233,7 +230,7 @@ public class WhisperServerService extends Application. - */ -package org.whispersystems.textsecuregcm.configuration; - -import com.fasterxml.jackson.annotation.JsonProperty; -import org.hibernate.validator.constraints.NotEmpty; - -public class MemcacheConfiguration { - - @NotEmpty - @JsonProperty - private String servers; - - @JsonProperty - private String user; - - @JsonProperty - private String password; - - - public String getServers() { - return servers; - } - - public String getUser() { - return user; - } - - public String getPassword() { - return password; - } -} diff --git a/src/main/java/org/whispersystems/textsecuregcm/configuration/DirectoryConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/configuration/RedisConfiguration.java similarity index 96% rename from src/main/java/org/whispersystems/textsecuregcm/configuration/DirectoryConfiguration.java rename to src/main/java/org/whispersystems/textsecuregcm/configuration/RedisConfiguration.java index a02a507c2..cd71ecac6 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/configuration/DirectoryConfiguration.java +++ b/src/main/java/org/whispersystems/textsecuregcm/configuration/RedisConfiguration.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.URL; -public class DirectoryConfiguration { +public class RedisConfiguration { @JsonProperty @NotEmpty diff --git a/src/main/java/org/whispersystems/textsecuregcm/limits/LeakyBucket.java b/src/main/java/org/whispersystems/textsecuregcm/limits/LeakyBucket.java index 61389d118..6f2b964fc 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/limits/LeakyBucket.java +++ b/src/main/java/org/whispersystems/textsecuregcm/limits/LeakyBucket.java @@ -16,14 +16,20 @@ */ package org.whispersystems.textsecuregcm.limits; -import java.io.Serializable; +import com.fasterxml.jackson.annotation.JsonProperty; -public class LeakyBucket implements Serializable { +public class LeakyBucket { + @JsonProperty private final int bucketSize; + + @JsonProperty private final double leakRatePerMillis; + @JsonProperty private int spaceRemaining; + + @JsonProperty private long lastUpdateTimeMillis; public LeakyBucket(int bucketSize, double leakRatePerMillis) { diff --git a/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiter.java b/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiter.java index 9d452b17d..45b5051c3 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiter.java +++ b/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiter.java @@ -19,27 +19,38 @@ package org.whispersystems.textsecuregcm.limits; import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.SharedMetricRegistries; -import net.spy.memcached.MemcachedClient; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException; import org.whispersystems.textsecuregcm.util.Constants; +import org.whispersystems.textsecuregcm.util.SystemMapper; + +import java.io.IOException; import static com.codahale.metrics.MetricRegistry.name; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; public class RateLimiter { - private final Meter meter; - private final MemcachedClient memcachedClient; - private final String name; - private final int bucketSize; - private final double leakRatePerMillis; + private final Logger logger = LoggerFactory.getLogger(RateLimiter.class); + private final ObjectMapper mapper = SystemMapper.getMapper(); - public RateLimiter(MemcachedClient memcachedClient, String name, + private final Meter meter; + private final JedisPool cacheClient; + private final String name; + private final int bucketSize; + private final double leakRatePerMillis; + + public RateLimiter(JedisPool cacheClient, String name, int bucketSize, double leakRatePerMinute) { MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME); this.meter = metricRegistry.meter(name(getClass(), name, "exceeded")); - this.memcachedClient = memcachedClient; + this.cacheClient = cacheClient; this.name = name; this.bucketSize = bucketSize; this.leakRatePerMillis = leakRatePerMinute / (60.0 * 1000.0); @@ -61,21 +72,29 @@ public class RateLimiter { } private void setBucket(String key, LeakyBucket bucket) { - memcachedClient.set(getBucketName(key), - (int)Math.ceil((bucketSize / leakRatePerMillis) / 1000), bucket); - } - - private LeakyBucket getBucket(String key) { - LeakyBucket bucket = (LeakyBucket)memcachedClient.get(getBucketName(key)); - - if (bucket == null) { - return new LeakyBucket(bucketSize, leakRatePerMillis); - } else { - return bucket; + try (Jedis jedis = cacheClient.getResource()) { + String serialized = mapper.writeValueAsString(bucket); + jedis.setex(getBucketName(key), (int) Math.ceil((bucketSize / leakRatePerMillis) / 1000), serialized); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException(e); } } + private LeakyBucket getBucket(String key) { + try (Jedis jedis = cacheClient.getResource()) { + String serialized = jedis.get(getBucketName(key)); + + if (serialized != null) { + return mapper.readValue(serialized, LeakyBucket.class); + } + } catch (IOException e) { + logger.warn("Deserialization error", e); + } + + return new LeakyBucket(bucketSize, leakRatePerMillis); + } + private String getBucketName(String key) { - return LeakyBucket.class.getSimpleName() + name + key; + return "leaky_bucket::" + name + "::" + key; } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiters.java b/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiters.java index 52bbc3a31..3efb9e2a7 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiters.java +++ b/src/main/java/org/whispersystems/textsecuregcm/limits/RateLimiters.java @@ -17,9 +17,10 @@ package org.whispersystems.textsecuregcm.limits; -import net.spy.memcached.MemcachedClient; import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration; +import redis.clients.jedis.JedisPool; + public class RateLimiters { private final RateLimiter smsDestinationLimiter; @@ -34,40 +35,40 @@ public class RateLimiters { private final RateLimiter allocateDeviceLimiter; private final RateLimiter verifyDeviceLimiter; - public RateLimiters(RateLimitsConfiguration config, MemcachedClient memcachedClient) { - this.smsDestinationLimiter = new RateLimiter(memcachedClient, "smsDestination", + public RateLimiters(RateLimitsConfiguration config, JedisPool cacheClient) { + this.smsDestinationLimiter = new RateLimiter(cacheClient, "smsDestination", config.getSmsDestination().getBucketSize(), config.getSmsDestination().getLeakRatePerMinute()); - this.voiceDestinationLimiter = new RateLimiter(memcachedClient, "voxDestination", + this.voiceDestinationLimiter = new RateLimiter(cacheClient, "voxDestination", config.getVoiceDestination().getBucketSize(), config.getVoiceDestination().getLeakRatePerMinute()); - this.verifyLimiter = new RateLimiter(memcachedClient, "verify", + this.verifyLimiter = new RateLimiter(cacheClient, "verify", config.getVerifyNumber().getBucketSize(), config.getVerifyNumber().getLeakRatePerMinute()); - this.attachmentLimiter = new RateLimiter(memcachedClient, "attachmentCreate", + this.attachmentLimiter = new RateLimiter(cacheClient, "attachmentCreate", config.getAttachments().getBucketSize(), config.getAttachments().getLeakRatePerMinute()); - this.contactsLimiter = new RateLimiter(memcachedClient, "contactsQuery", + this.contactsLimiter = new RateLimiter(cacheClient, "contactsQuery", config.getContactQueries().getBucketSize(), config.getContactQueries().getLeakRatePerMinute()); - this.preKeysLimiter = new RateLimiter(memcachedClient, "prekeys", + this.preKeysLimiter = new RateLimiter(cacheClient, "prekeys", config.getPreKeys().getBucketSize(), config.getPreKeys().getLeakRatePerMinute()); - this.messagesLimiter = new RateLimiter(memcachedClient, "messages", + this.messagesLimiter = new RateLimiter(cacheClient, "messages", config.getMessages().getBucketSize(), config.getMessages().getLeakRatePerMinute()); - this.allocateDeviceLimiter = new RateLimiter(memcachedClient, "allocateDevice", + this.allocateDeviceLimiter = new RateLimiter(cacheClient, "allocateDevice", config.getAllocateDevice().getBucketSize(), config.getAllocateDevice().getLeakRatePerMinute()); - this.verifyDeviceLimiter = new RateLimiter(memcachedClient, "verifyDevice", + this.verifyDeviceLimiter = new RateLimiter(cacheClient, "verifyDevice", config.getVerifyDevice().getBucketSize(), config.getVerifyDevice().getLeakRatePerMinute()); diff --git a/src/main/java/org/whispersystems/textsecuregcm/providers/MemcacheHealthCheck.java b/src/main/java/org/whispersystems/textsecuregcm/providers/MemcacheHealthCheck.java deleted file mode 100644 index b28fadc2a..000000000 --- a/src/main/java/org/whispersystems/textsecuregcm/providers/MemcacheHealthCheck.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (C) 2013 Open WhisperSystems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.whispersystems.textsecuregcm.providers; - -import com.codahale.metrics.health.HealthCheck; -import net.spy.memcached.MemcachedClient; - -import java.security.SecureRandom; - -public class MemcacheHealthCheck extends HealthCheck { - - private final MemcachedClient client; - - public MemcacheHealthCheck(MemcachedClient client) { - this.client = client; - } - - @Override - protected Result check() throws Exception { - if (client == null) { - return Result.unhealthy("not configured"); - } - - int random = SecureRandom.getInstance("SHA1PRNG").nextInt(); - int value = SecureRandom.getInstance("SHA1PRNG").nextInt(); - - this.client.set("HEALTH" + random, 2000, String.valueOf(value)); - String result = (String)this.client.get("HEALTH" + random); - - if (result == null || Integer.parseInt(result) != value) { - return Result.unhealthy("Fetch failed"); - } - - this.client.delete("HEALTH" + random); - - return Result.healthy(); - } - -} diff --git a/src/main/java/org/whispersystems/textsecuregcm/providers/MemcachedClientFactory.java b/src/main/java/org/whispersystems/textsecuregcm/providers/MemcachedClientFactory.java deleted file mode 100644 index e73873780..000000000 --- a/src/main/java/org/whispersystems/textsecuregcm/providers/MemcachedClientFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (C) 2013 Open WhisperSystems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.whispersystems.textsecuregcm.providers; - -import net.spy.memcached.AddrUtil; -import net.spy.memcached.ConnectionFactoryBuilder; -import net.spy.memcached.MemcachedClient; -import net.spy.memcached.auth.AuthDescriptor; -import net.spy.memcached.auth.PlainCallbackHandler; -import org.whispersystems.textsecuregcm.configuration.MemcacheConfiguration; -import org.whispersystems.textsecuregcm.util.Util; - -import java.io.IOException; - -public class MemcachedClientFactory { - - private final MemcachedClient client; - - public MemcachedClientFactory(MemcacheConfiguration config) throws IOException { - ConnectionFactoryBuilder builder = new ConnectionFactoryBuilder(); - builder.setProtocol(ConnectionFactoryBuilder.Protocol.BINARY); - - if (!Util.isEmpty(config.getUser())) { - AuthDescriptor ad = new AuthDescriptor(new String[] { "PLAIN" }, - new PlainCallbackHandler(config.getUser(), - config.getPassword())); - - builder.setAuthDescriptor(ad); - } - - - this.client = new MemcachedClient(builder.build(), - AddrUtil.getAddresses(config.getServers())); - } - - - public MemcachedClient getClient() { - return client; - } -} diff --git a/src/main/java/org/whispersystems/textsecuregcm/providers/RedisClientFactory.java b/src/main/java/org/whispersystems/textsecuregcm/providers/RedisClientFactory.java index 8a5692b44..abdd4f13c 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/providers/RedisClientFactory.java +++ b/src/main/java/org/whispersystems/textsecuregcm/providers/RedisClientFactory.java @@ -16,7 +16,6 @@ */ package org.whispersystems.textsecuregcm.providers; -import org.whispersystems.textsecuregcm.configuration.DirectoryConfiguration; import org.whispersystems.textsecuregcm.util.Util; import java.net.URI; diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java b/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java index bb0f4e275..56dce8eb8 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java @@ -17,12 +17,9 @@ package org.whispersystems.textsecuregcm.storage; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Optional; -import net.spy.memcached.MemcachedClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.entities.ClientContact; @@ -33,23 +30,26 @@ import java.io.IOException; import java.util.Iterator; import java.util.List; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + public class AccountsManager { private final Logger logger = LoggerFactory.getLogger(AccountsManager.class); private final Accounts accounts; - private final MemcachedClient memcachedClient; + private final JedisPool cacheClient; private final DirectoryManager directory; private final ObjectMapper mapper; public AccountsManager(Accounts accounts, DirectoryManager directory, - MemcachedClient memcachedClient) + JedisPool cacheClient) { - this.accounts = accounts; - this.directory = directory; - this.memcachedClient = memcachedClient; - this.mapper = SystemMapper.getMapper(); + this.accounts = accounts; + this.directory = directory; + this.cacheClient = cacheClient; + this.mapper = SystemMapper.getMapper(); } public long getCount() { @@ -112,25 +112,19 @@ public class AccountsManager { } private void memcacheSet(String number, Account account) { - if (memcachedClient != null) { - try { - String json = mapper.writeValueAsString(account); - memcachedClient.set(getKey(number), 0, json); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException(e); - } + try (Jedis jedis = cacheClient.getResource()) { + jedis.set(getKey(number), mapper.writeValueAsString(account)); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException(e); } } private Optional memcacheGet(String number) { - if (memcachedClient == null) return Optional.absent(); - - try { - String json = (String)memcachedClient.get(getKey(number)); + try (Jedis jedis = cacheClient.getResource()) { + String json = jedis.get(getKey(number)); if (json != null) return Optional.of(mapper.readValue(json, Account.class)); else return Optional.absent(); - } catch (IOException e) { logger.warn("AccountsManager", "Deserialization error", e); return Optional.absent(); diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccountsManager.java b/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccountsManager.java index db95f5f50..3c23e5d2e 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccountsManager.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccountsManager.java @@ -17,20 +17,21 @@ package org.whispersystems.textsecuregcm.storage; import com.google.common.base.Optional; -import net.spy.memcached.MemcachedClient; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; public class PendingAccountsManager { - private static final String MEMCACHE_PREFIX = "pending_account"; + private static final String CACHE_PREFIX = "pending_account::"; private final PendingAccounts pendingAccounts; - private final MemcachedClient memcachedClient; + private final JedisPool cacheClient; - public PendingAccountsManager(PendingAccounts pendingAccounts, - MemcachedClient memcachedClient) + public PendingAccountsManager(PendingAccounts pendingAccounts, JedisPool cacheClient) { this.pendingAccounts = pendingAccounts; - this.memcachedClient = memcachedClient; + this.cacheClient = cacheClient; } public void store(String number, String code) { @@ -58,22 +59,20 @@ public class PendingAccountsManager { } private void memcacheSet(String number, String code) { - if (memcachedClient != null) { - memcachedClient.set(MEMCACHE_PREFIX + number, 0, code); + try (Jedis jedis = cacheClient.getResource()) { + jedis.set(CACHE_PREFIX + number, code); } } private Optional memcacheGet(String number) { - if (memcachedClient != null) { - return Optional.fromNullable((String)memcachedClient.get(MEMCACHE_PREFIX + number)); - } else { - return Optional.absent(); + try (Jedis jedis = cacheClient.getResource()) { + return Optional.fromNullable(jedis.get(CACHE_PREFIX + number)); } } private void memcacheDelete(String number) { - if (memcachedClient != null) { - memcachedClient.delete(MEMCACHE_PREFIX + number); + try (Jedis jedis = cacheClient.getResource()) { + jedis.del(CACHE_PREFIX + number); } } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/PendingDevicesManager.java b/src/main/java/org/whispersystems/textsecuregcm/storage/PendingDevicesManager.java index 4222ee570..dbac8c462 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/PendingDevicesManager.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/PendingDevicesManager.java @@ -17,20 +17,22 @@ package org.whispersystems.textsecuregcm.storage; import com.google.common.base.Optional; -import net.spy.memcached.MemcachedClient; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; public class PendingDevicesManager { - private static final String MEMCACHE_PREFIX = "pending_devices"; + private static final String CACHE_PREFIX = "pending_devices::"; private final PendingDevices pendingDevices; - private final MemcachedClient memcachedClient; + private final JedisPool cacheClient; public PendingDevicesManager(PendingDevices pendingDevices, - MemcachedClient memcachedClient) + JedisPool cacheClient) { - this.pendingDevices = pendingDevices; - this.memcachedClient = memcachedClient; + this.pendingDevices = pendingDevices; + this.cacheClient = cacheClient; } public void store(String number, String code) { @@ -58,22 +60,20 @@ public class PendingDevicesManager { } private void memcacheSet(String number, String code) { - if (memcachedClient != null) { - memcachedClient.set(MEMCACHE_PREFIX + number, 0, code); + try (Jedis jedis = cacheClient.getResource()) { + jedis.set(CACHE_PREFIX + number, code); } } private Optional memcacheGet(String number) { - if (memcachedClient != null) { - return Optional.fromNullable((String)memcachedClient.get(MEMCACHE_PREFIX + number)); - } else { - return Optional.absent(); + try (Jedis jedis = cacheClient.getResource()) { + return Optional.fromNullable(jedis.get(CACHE_PREFIX + number)); } } private void memcacheDelete(String number) { - if (memcachedClient != null) { - memcachedClient.delete(MEMCACHE_PREFIX + number); + try (Jedis jedis = cacheClient.getResource()) { + jedis.del(CACHE_PREFIX + number); } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryCommand.java b/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryCommand.java index ec3ca8b20..aacccaf46 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryCommand.java +++ b/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryCommand.java @@ -17,13 +17,11 @@ package org.whispersystems.textsecuregcm.workers; import net.sourceforge.argparse4j.inf.Namespace; -import net.spy.memcached.MemcachedClient; import org.skife.jdbi.v2.DBI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.WhisperServerConfiguration; import org.whispersystems.textsecuregcm.federation.FederatedClientManager; -import org.whispersystems.textsecuregcm.providers.MemcachedClientFactory; import org.whispersystems.textsecuregcm.providers.RedisClientFactory; import org.whispersystems.textsecuregcm.storage.Accounts; import org.whispersystems.textsecuregcm.storage.AccountsManager; @@ -62,10 +60,10 @@ public class DirectoryCommand extends ConfiguredCommand