Refactor to use shared recurringJobExecutor
This commit is contained in:
		
							parent
							
								
									819d59cd79
								
							
						
					
					
						commit
						6fa9dcd954
					
				| 
						 | 
					@ -400,7 +400,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
 | 
				
			||||||
    BlockingQueue<Runnable> keyspaceNotificationDispatchQueue = new ArrayBlockingQueue<>(10_000);
 | 
					    BlockingQueue<Runnable> keyspaceNotificationDispatchQueue = new ArrayBlockingQueue<>(10_000);
 | 
				
			||||||
    Metrics.gaugeCollectionSize(name(getClass(), "keyspaceNotificationDispatchQueueSize"), Collections.emptyList(), keyspaceNotificationDispatchQueue);
 | 
					    Metrics.gaugeCollectionSize(name(getClass(), "keyspaceNotificationDispatchQueueSize"), Collections.emptyList(), keyspaceNotificationDispatchQueue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ScheduledExecutorService recurringJobExecutor                 = environment.lifecycle().scheduledExecutorService(name(getClass(), "recurringJob-%d")).threads(2).build();
 | 
					    ScheduledExecutorService recurringJobExecutor                 = environment.lifecycle().scheduledExecutorService(name(getClass(), "recurringJob-%d")).threads(3).build();
 | 
				
			||||||
    ScheduledExecutorService declinedMessageReceiptExecutor       = environment.lifecycle().scheduledExecutorService(name(getClass(), "declined-receipt-%d")).threads(2).build();
 | 
					    ScheduledExecutorService declinedMessageReceiptExecutor       = environment.lifecycle().scheduledExecutorService(name(getClass(), "declined-receipt-%d")).threads(2).build();
 | 
				
			||||||
    ScheduledExecutorService retrySchedulingExecutor              = environment.lifecycle().scheduledExecutorService(name(getClass(), "retry-%d")).threads(2).build();
 | 
					    ScheduledExecutorService retrySchedulingExecutor              = environment.lifecycle().scheduledExecutorService(name(getClass(), "retry-%d")).threads(2).build();
 | 
				
			||||||
    ExecutorService          keyspaceNotificationDispatchExecutor = environment.lifecycle().executorService(name(getClass(), "keyspaceNotification-%d")).maxThreads(16).workQueue(keyspaceNotificationDispatchQueue).build();
 | 
					    ExecutorService          keyspaceNotificationDispatchExecutor = environment.lifecycle().executorService(name(getClass(), "keyspaceNotification-%d")).maxThreads(16).workQueue(keyspaceNotificationDispatchQueue).build();
 | 
				
			||||||
| 
						 | 
					@ -494,7 +494,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
 | 
				
			||||||
    AccountDatabaseCrawlerCache accountDatabaseCrawlerCache = new AccountDatabaseCrawlerCache(cacheCluster);
 | 
					    AccountDatabaseCrawlerCache accountDatabaseCrawlerCache = new AccountDatabaseCrawlerCache(cacheCluster);
 | 
				
			||||||
    AccountDatabaseCrawler      accountDatabaseCrawler      = new AccountDatabaseCrawler(accountsManager, accountDatabaseCrawlerCache, accountDatabaseCrawlerListeners, config.getAccountDatabaseCrawlerConfiguration().getChunkSize(), config.getAccountDatabaseCrawlerConfiguration().getChunkIntervalMs());
 | 
					    AccountDatabaseCrawler      accountDatabaseCrawler      = new AccountDatabaseCrawler(accountsManager, accountDatabaseCrawlerCache, accountDatabaseCrawlerListeners, config.getAccountDatabaseCrawlerConfiguration().getChunkSize(), config.getAccountDatabaseCrawlerConfiguration().getChunkIntervalMs());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DeletedAccountsTableCrawler deletedAccountsTableCrawler = new DeletedAccountsTableCrawler(deletedAccounts, deletedAccountsDirectoryReconcilers, cacheCluster);
 | 
					    DeletedAccountsTableCrawler deletedAccountsTableCrawler = new DeletedAccountsTableCrawler(deletedAccounts, deletedAccountsDirectoryReconcilers, cacheCluster, recurringJobExecutor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    apnSender.setApnFallbackManager(apnFallbackManager);
 | 
					    apnSender.setApnFallbackManager(apnFallbackManager);
 | 
				
			||||||
    environment.lifecycle().manage(apnFallbackManager);
 | 
					    environment.lifecycle().manage(apnFallbackManager);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ import java.io.IOException;
 | 
				
			||||||
import java.time.Duration;
 | 
					import java.time.Duration;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.UUID;
 | 
					import java.util.UUID;
 | 
				
			||||||
 | 
					import java.util.concurrent.ScheduledExecutorService;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
import org.whispersystems.textsecuregcm.entities.DirectoryReconciliationRequest.User;
 | 
					import org.whispersystems.textsecuregcm.entities.DirectoryReconciliationRequest.User;
 | 
				
			||||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
 | 
					import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
 | 
				
			||||||
| 
						 | 
					@ -32,9 +33,10 @@ public class DeletedAccountsTableCrawler extends ManagedPeriodicWork {
 | 
				
			||||||
  public DeletedAccountsTableCrawler(
 | 
					  public DeletedAccountsTableCrawler(
 | 
				
			||||||
      final DeletedAccounts deletedAccounts,
 | 
					      final DeletedAccounts deletedAccounts,
 | 
				
			||||||
      final List<DeletedAccountsDirectoryReconciler> reconcilers,
 | 
					      final List<DeletedAccountsDirectoryReconciler> reconcilers,
 | 
				
			||||||
      final FaultTolerantRedisCluster cluster) throws IOException {
 | 
					      final FaultTolerantRedisCluster cluster,
 | 
				
			||||||
 | 
					      final ScheduledExecutorService executorService) throws IOException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    super(new ManagedPeriodicWorkLock(ACTIVE_WORKER_KEY, cluster), WORKER_TTL, RUN_INTERVAL);
 | 
					    super(new ManagedPeriodicWorkLock(ACTIVE_WORKER_KEY, cluster), WORKER_TTL, RUN_INTERVAL, executorService);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.deletedAccounts = deletedAccounts;
 | 
					    this.deletedAccounts = deletedAccounts;
 | 
				
			||||||
    this.reconcilers = reconcilers;
 | 
					    this.reconcilers = reconcilers;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,12 +4,16 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
package org.whispersystems.textsecuregcm.storage;
 | 
					package org.whispersystems.textsecuregcm.storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static com.codahale.metrics.MetricRegistry.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io.dropwizard.lifecycle.Managed;
 | 
					import io.dropwizard.lifecycle.Managed;
 | 
				
			||||||
 | 
					import io.micrometer.core.instrument.Metrics;
 | 
				
			||||||
import java.time.Duration;
 | 
					import java.time.Duration;
 | 
				
			||||||
import java.util.UUID;
 | 
					import java.util.UUID;
 | 
				
			||||||
import java.util.concurrent.Executors;
 | 
					 | 
				
			||||||
import java.util.concurrent.ScheduledExecutorService;
 | 
					import java.util.concurrent.ScheduledExecutorService;
 | 
				
			||||||
 | 
					import java.util.concurrent.ScheduledFuture;
 | 
				
			||||||
import java.util.concurrent.TimeUnit;
 | 
					import java.util.concurrent.TimeUnit;
 | 
				
			||||||
 | 
					import java.util.concurrent.TimeoutException;
 | 
				
			||||||
import java.util.concurrent.atomic.AtomicBoolean;
 | 
					import java.util.concurrent.atomic.AtomicBoolean;
 | 
				
			||||||
import org.slf4j.Logger;
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
import org.slf4j.LoggerFactory;
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
| 
						 | 
					@ -19,6 +23,8 @@ public abstract class ManagedPeriodicWork implements Managed {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private final Logger logger = LoggerFactory.getLogger(getClass());
 | 
					  private final Logger logger = LoggerFactory.getLogger(getClass());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private static final String FUTURE_DONE_GAUGE_NAME = "futureDone";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private final ManagedPeriodicWorkLock lock;
 | 
					  private final ManagedPeriodicWorkLock lock;
 | 
				
			||||||
  private final Duration workerTtl;
 | 
					  private final Duration workerTtl;
 | 
				
			||||||
  private final Duration runInterval;
 | 
					  private final Duration runInterval;
 | 
				
			||||||
| 
						 | 
					@ -27,17 +33,24 @@ public abstract class ManagedPeriodicWork implements Managed {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private final AtomicBoolean started = new AtomicBoolean(false);
 | 
					  private final AtomicBoolean started = new AtomicBoolean(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private ScheduledFuture<?> scheduledFuture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public ManagedPeriodicWork(final ManagedPeriodicWorkLock lock, final Duration workerTtl, final Duration runInterval) {
 | 
					  public ManagedPeriodicWork(final ManagedPeriodicWorkLock lock, final Duration workerTtl, final Duration runInterval, final ScheduledExecutorService scheduledExecutorService) {
 | 
				
			||||||
    this.lock = lock;
 | 
					    this.lock = lock;
 | 
				
			||||||
    this.workerTtl = workerTtl;
 | 
					    this.workerTtl = workerTtl;
 | 
				
			||||||
    this.runInterval = runInterval;
 | 
					    this.runInterval = runInterval;
 | 
				
			||||||
    this.workerId = UUID.randomUUID().toString();
 | 
					    this.workerId = UUID.randomUUID().toString();
 | 
				
			||||||
    this.executorService = Executors.newSingleThreadScheduledExecutor((runnable) -> new Thread(runnable, getClass().getName()));
 | 
					    this.executorService = scheduledExecutorService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Metrics.gauge(name(getClass(), FUTURE_DONE_GAUGE_NAME), this, ManagedPeriodicWork::isFutureDone);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  abstract protected void doPeriodicWork() throws Exception;
 | 
					  abstract protected void doPeriodicWork() throws Exception;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int isFutureDone() {
 | 
				
			||||||
 | 
					    return scheduledFuture.isDone() ? 1 : 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public synchronized void start() throws Exception {
 | 
					  public synchronized void start() throws Exception {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +58,7 @@ public abstract class ManagedPeriodicWork implements Managed {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    executorService.scheduleAtFixedRate(() -> {
 | 
					    scheduledFuture = executorService.scheduleAtFixedRate(() -> {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
          execute();
 | 
					          execute();
 | 
				
			||||||
        } catch (final Exception e) {
 | 
					        } catch (final Exception e) {
 | 
				
			||||||
| 
						 | 
					@ -60,13 +73,20 @@ public abstract class ManagedPeriodicWork implements Managed {
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public synchronized void stop() throws Exception {
 | 
					  public synchronized void stop() throws Exception {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    executorService.shutdown();
 | 
					    if (scheduledFuture != null) {
 | 
				
			||||||
 | 
					      scheduledFuture.cancel(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    boolean terminated = false;
 | 
					      boolean terminated = false;
 | 
				
			||||||
    while (!terminated) {
 | 
					      while (!terminated) {
 | 
				
			||||||
      terminated = executorService.awaitTermination(5, TimeUnit.MINUTES);
 | 
					        try {
 | 
				
			||||||
      if (!terminated) {
 | 
					          scheduledFuture.get(5, TimeUnit.MINUTES);
 | 
				
			||||||
        logger.warn("worker not yet terminated");
 | 
					          terminated = true;
 | 
				
			||||||
 | 
					        } catch (final TimeoutException e) {
 | 
				
			||||||
 | 
					          logger.warn("worker not yet terminated");
 | 
				
			||||||
 | 
					        } catch (final Exception e) {
 | 
				
			||||||
 | 
					          logger.warn("worker terminated exceptionally", e);
 | 
				
			||||||
 | 
					          terminated = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue