View Javadoc
1   package com.atlassian.activeobjects.confluence;
2   
3   import com.atlassian.activeobjects.spi.DatabaseType;
4   import com.atlassian.activeobjects.spi.DefaultInitExecutorServiceProvider;
5   import com.atlassian.activeobjects.spi.InitExecutorServiceProvider;
6   import com.atlassian.activeobjects.spi.TenantAwareDataSourceProvider;
7   import com.atlassian.sal.api.executor.ThreadLocalDelegateExecutorFactory;
8   import com.atlassian.tenancy.api.Tenant;
9   import com.google.common.annotations.VisibleForTesting;
10  import com.google.common.util.concurrent.MoreExecutors;
11  import org.slf4j.Logger;
12  import org.slf4j.LoggerFactory;
13  
14  import javax.annotation.Nonnull;
15  import java.util.concurrent.ExecutorService;
16  
17  import static com.google.common.base.Preconditions.checkNotNull;
18  
19  public class ConfluenceInitExecutorServiceProvider implements InitExecutorServiceProvider {
20      private static final Logger logger = LoggerFactory.getLogger(DefaultInitExecutorServiceProvider.class);
21  
22      private final TenantAwareDataSourceProvider tenantAwareDataSourceProvider;
23      private final ThreadLocalDelegateExecutorFactory threadLocalDelegateExecutorFactory;
24  
25      @VisibleForTesting
26      final InitExecutorServiceProvider defaultInitExecutorServiceProvider;
27  
28      public ConfluenceInitExecutorServiceProvider(
29              final ThreadLocalDelegateExecutorFactory threadLocalDelegateExecutorFactory,
30              final TenantAwareDataSourceProvider tenantAwareDataSourceProvider,
31              final InitExecutorServiceProvider defaultInitExecutorServiceProvider) {
32          this.threadLocalDelegateExecutorFactory = checkNotNull(threadLocalDelegateExecutorFactory);
33          this.tenantAwareDataSourceProvider = checkNotNull(tenantAwareDataSourceProvider);
34          this.defaultInitExecutorServiceProvider = checkNotNull(defaultInitExecutorServiceProvider);
35      }
36  
37      /**
38       * In the case of HSQL, confluence will dispatch TenantArrivedEvent synchronously. We then execute the init operations
39       * in the same thread, so that we don't have multi threads i.e. transactions attempting DDL against the alleged
40       * database HSQL.
41       *
42       * In other cases it will defer to the default.
43       *
44       * @return same thread executor for HSQL
45       */
46      @Nonnull
47      @Override
48      public ExecutorService initExecutorService(@Nonnull Tenant tenant) {
49          DatabaseType databaseType = tenantAwareDataSourceProvider.getDatabaseType(tenant);
50          if (DatabaseType.HSQL.equals(databaseType)) {
51              logger.debug("creating HSQL snowflake init executor");
52              return threadLocalDelegateExecutorFactory.createExecutorService(MoreExecutors.sameThreadExecutor());
53          } else {
54              return defaultInitExecutorServiceProvider.initExecutorService(tenant);
55          }
56      }
57  }