Use a memoizing supplier instead of a looping thread to cache remote config entries
This commit is contained in:
parent
d89b4f7e95
commit
048e17c62b
|
@ -593,7 +593,6 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
environment.lifecycle().manage(accountDatabaseCrawler);
|
environment.lifecycle().manage(accountDatabaseCrawler);
|
||||||
environment.lifecycle().manage(directoryReconciliationAccountDatabaseCrawler);
|
environment.lifecycle().manage(directoryReconciliationAccountDatabaseCrawler);
|
||||||
environment.lifecycle().manage(deletedAccountsTableCrawler);
|
environment.lifecycle().manage(deletedAccountsTableCrawler);
|
||||||
environment.lifecycle().manage(remoteConfigsManager);
|
|
||||||
environment.lifecycle().manage(messagesCache);
|
environment.lifecycle().manage(messagesCache);
|
||||||
environment.lifecycle().manage(messagePersister);
|
environment.lifecycle().manage(messagePersister);
|
||||||
environment.lifecycle().manage(clientPresenceManager);
|
environment.lifecycle().manage(clientPresenceManager);
|
||||||
|
|
|
@ -5,70 +5,26 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.storage;
|
package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.base.Suppliers;
|
||||||
import io.dropwizard.lifecycle.Managed;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.whispersystems.textsecuregcm.util.Util;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class RemoteConfigsManager implements Managed {
|
public class RemoteConfigsManager {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(RemoteConfigsManager.class);
|
|
||||||
|
|
||||||
private final RemoteConfigs remoteConfigs;
|
private final RemoteConfigs remoteConfigs;
|
||||||
private final long sleepInterval;
|
|
||||||
|
|
||||||
private final AtomicReference<List<RemoteConfig>> cachedConfigs = new AtomicReference<>(new LinkedList<>());
|
private final Supplier<List<RemoteConfig>> remoteConfigSupplier;
|
||||||
|
|
||||||
public RemoteConfigsManager(RemoteConfigs remoteConfigs) {
|
public RemoteConfigsManager(RemoteConfigs remoteConfigs) {
|
||||||
this(remoteConfigs, TimeUnit.SECONDS.toMillis(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public RemoteConfigsManager(RemoteConfigs remoteConfigs, long sleepInterval) {
|
|
||||||
this.remoteConfigs = remoteConfigs;
|
this.remoteConfigs = remoteConfigs;
|
||||||
this.sleepInterval = sleepInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
remoteConfigSupplier =
|
||||||
public void start() {
|
Suppliers.memoizeWithExpiration(remoteConfigs::getAll, 10, TimeUnit.SECONDS);
|
||||||
refreshCache();
|
|
||||||
|
|
||||||
new Thread(() -> {
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
refreshCache();
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.warn("Error updating remote configs cache", t);
|
|
||||||
}
|
|
||||||
|
|
||||||
Util.sleep(sleepInterval);
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshCache() {
|
|
||||||
this.cachedConfigs.set(remoteConfigs.getAll());
|
|
||||||
|
|
||||||
synchronized (this.cachedConfigs) {
|
|
||||||
this.cachedConfigs.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
void waitForCacheRefresh() throws InterruptedException {
|
|
||||||
synchronized (this.cachedConfigs) {
|
|
||||||
this.cachedConfigs.wait();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RemoteConfig> getAll() {
|
public List<RemoteConfig> getAll() {
|
||||||
return cachedConfigs.get();
|
return remoteConfigSupplier.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(RemoteConfig config) {
|
public void set(RemoteConfig config) {
|
||||||
|
@ -78,9 +34,4 @@ public class RemoteConfigsManager implements Managed {
|
||||||
public void delete(String name) {
|
public void delete(String name) {
|
||||||
remoteConfigs.delete(name);
|
remoteConfigs.delete(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,21 +29,18 @@ public class RemoteConfigsManagerTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
RemoteConfigs remoteConfigs = new RemoteConfigs(new FaultTolerantDatabase("remote_configs-test", Jdbi.create(db.getTestDatabase()), new CircuitBreakerConfiguration()));
|
this.remoteConfigs = new RemoteConfigsManager(new RemoteConfigs(
|
||||||
this.remoteConfigs = new RemoteConfigsManager(remoteConfigs, 500);
|
new FaultTolerantDatabase("remote_configs-test", Jdbi.create(db.getTestDatabase()), new CircuitBreakerConfiguration())));
|
||||||
this.remoteConfigs.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdate() throws InterruptedException {
|
public void testUpdate() {
|
||||||
remoteConfigs.set(new RemoteConfig("android.stickers", 50, Set.of(AuthHelper.VALID_UUID), "FALSE", "TRUE", null));
|
remoteConfigs.set(new RemoteConfig("android.stickers", 50, Set.of(AuthHelper.VALID_UUID), "FALSE", "TRUE", null));
|
||||||
remoteConfigs.set(new RemoteConfig("value.sometimes", 50, Set.of(), "bar", "baz", null));
|
remoteConfigs.set(new RemoteConfig("value.sometimes", 50, Set.of(), "bar", "baz", null));
|
||||||
remoteConfigs.set(new RemoteConfig("ios.stickers", 50, Set.of(), "FALSE", "TRUE", null));
|
remoteConfigs.set(new RemoteConfig("ios.stickers", 50, Set.of(), "FALSE", "TRUE", null));
|
||||||
remoteConfigs.set(new RemoteConfig("ios.stickers", 75, Set.of(), "FALSE", "TRUE", null));
|
remoteConfigs.set(new RemoteConfig("ios.stickers", 75, Set.of(), "FALSE", "TRUE", null));
|
||||||
remoteConfigs.set(new RemoteConfig("value.sometimes", 25, Set.of(AuthHelper.VALID_UUID), "abc", "def", null));
|
remoteConfigs.set(new RemoteConfig("value.sometimes", 25, Set.of(AuthHelper.VALID_UUID), "abc", "def", null));
|
||||||
|
|
||||||
remoteConfigs.waitForCacheRefresh();
|
|
||||||
|
|
||||||
List<RemoteConfig> results = remoteConfigs.getAll();
|
List<RemoteConfig> results = remoteConfigs.getAll();
|
||||||
|
|
||||||
assertThat(results.size()).isEqualTo(3);
|
assertThat(results.size()).isEqualTo(3);
|
||||||
|
|
Loading…
Reference in New Issue