Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
gthea committed Dec 2, 2024
1 parent 428bb5b commit 4532d4a
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 43 deletions.
83 changes: 82 additions & 1 deletion src/main/java/io/split/android/client/SplitFactoryHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.util.Pair;
import androidx.work.WorkManager;

Expand All @@ -22,11 +23,16 @@

import io.split.android.client.common.CompressionUtilProvider;
import io.split.android.client.events.EventsManagerCoordinator;
import io.split.android.client.events.SplitInternalEvent;
import io.split.android.client.lifecycle.SplitLifecycleManager;
import io.split.android.client.network.HttpClient;
import io.split.android.client.network.SdkTargetPath;
import io.split.android.client.network.SplitHttpHeadersBuilder;
import io.split.android.client.service.ServiceFactory;
import io.split.android.client.service.SplitApiFacade;
import io.split.android.client.service.executor.SplitSingleThreadTaskExecutor;
import io.split.android.client.service.executor.SplitTaskExecutionInfo;
import io.split.android.client.service.executor.SplitTaskExecutionListener;
import io.split.android.client.service.executor.SplitTaskExecutor;
import io.split.android.client.service.executor.SplitTaskFactory;
import io.split.android.client.service.http.mysegments.MySegmentsFetcherFactory;
Expand Down Expand Up @@ -55,6 +61,8 @@
import io.split.android.client.service.sseclient.sseclient.SseHandler;
import io.split.android.client.service.sseclient.sseclient.SseRefreshTokenTimer;
import io.split.android.client.service.sseclient.sseclient.StreamingComponents;
import io.split.android.client.service.synchronizer.RolloutCacheManager;
import io.split.android.client.service.synchronizer.RolloutCacheManagerImpl;
import io.split.android.client.service.synchronizer.SyncGuardian;
import io.split.android.client.service.synchronizer.SyncGuardianImpl;
import io.split.android.client.service.synchronizer.SyncManager;
Expand Down Expand Up @@ -84,6 +92,7 @@
import io.split.android.client.telemetry.storage.TelemetryRuntimeProducer;
import io.split.android.client.telemetry.storage.TelemetryStorage;
import io.split.android.client.utils.Utils;
import io.split.android.client.utils.logger.Logger;

class SplitFactoryHelper {
private static final int DB_MAGIC_CHARS_COUNT = 4;
Expand Down Expand Up @@ -397,7 +406,8 @@ public ProcessStrategy getImpressionStrategy(SplitTaskExecutor splitTaskExecutor
.getStrategy(config.impressionsMode());
}

@Nullable SplitCipher getCipher(String apiKey, boolean encryptionEnabled) {
@Nullable
SplitCipher getCipher(String apiKey, boolean encryptionEnabled) {
return SplitCipherFactory.create(apiKey, encryptionEnabled ? SplitEncryptionLevel.AES_128_CBC :
SplitEncryptionLevel.NONE);
}
Expand Down Expand Up @@ -472,4 +482,75 @@ public URI build(String matchingKey) throws URISyntaxException {
return SdkTargetPath.mySegments(mEndpoint, matchingKey);
}
}

static class Initializer implements Runnable {

private final RolloutCacheManager mRolloutCacheManager;
private final SplitTaskExecutionListener mListener;

Initializer(
String apiToken,
SplitClientConfig config,
SplitTaskFactory splitTaskFactory,
SplitRoomDatabase splitDatabase,
SplitCipher splitCipher,
EventsManagerCoordinator eventsManagerCoordinator,
SplitTaskExecutor splitTaskExecutor,
SplitSingleThreadTaskExecutor splitSingleThreadTaskExecutor,
SplitStorageContainer storageContainer,
SyncManager syncManager,
SplitLifecycleManager lifecycleManager) {

this(new RolloutCacheManagerImpl(config,
storageContainer,
splitTaskFactory.createCleanUpDatabaseTask(System.currentTimeMillis() / 1000),
splitTaskFactory.createEncryptionMigrationTask(apiToken, splitDatabase, config.encryptionEnabled(), splitCipher)),
new Listener(eventsManagerCoordinator, splitTaskExecutor, splitSingleThreadTaskExecutor, syncManager, lifecycleManager));
}

@VisibleForTesting
Initializer(RolloutCacheManager rolloutCacheManager, SplitTaskExecutionListener listener) {
mRolloutCacheManager = rolloutCacheManager;
mListener = listener;
}

@Override
public void run() {
mRolloutCacheManager.validateCache(mListener);
}

static class Listener implements SplitTaskExecutionListener {

private final EventsManagerCoordinator mEventsManagerCoordinator;
private final SplitTaskExecutor mSplitTaskExecutor;
private final SplitSingleThreadTaskExecutor mSplitSingleThreadTaskExecutor;
private final SyncManager mSyncManager;
private final SplitLifecycleManager mLifecycleManager;

Listener(EventsManagerCoordinator eventsManagerCoordinator,
SplitTaskExecutor splitTaskExecutor,
SplitSingleThreadTaskExecutor splitSingleThreadTaskExecutor,
SyncManager syncManager,
SplitLifecycleManager lifecycleManager) {
mEventsManagerCoordinator = eventsManagerCoordinator;
mSplitTaskExecutor = splitTaskExecutor;
mSplitSingleThreadTaskExecutor = splitSingleThreadTaskExecutor;
mSyncManager = syncManager;
mLifecycleManager = lifecycleManager;
}

@Override
public void taskExecuted(@NonNull SplitTaskExecutionInfo taskInfo) {
mEventsManagerCoordinator.notifyInternalEvent(SplitInternalEvent.ENCRYPTION_MIGRATION_DONE);

mSplitTaskExecutor.resume();
mSplitSingleThreadTaskExecutor.resume();

mSyncManager.start();
mLifecycleManager.register(mSyncManager);

Logger.i("Android SDK initialized!");
}
}
}
}
46 changes: 16 additions & 30 deletions src/main/java/io/split/android/client/SplitFactoryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import io.split.android.client.api.Key;
import io.split.android.client.common.CompressionUtilProvider;
import io.split.android.client.events.EventsManagerCoordinator;
import io.split.android.client.events.SplitInternalEvent;
import io.split.android.client.factory.FactoryMonitor;
import io.split.android.client.factory.FactoryMonitorImpl;
import io.split.android.client.impressions.ImpressionListener;
Expand All @@ -29,16 +28,13 @@
import io.split.android.client.network.HttpClientImpl;
import io.split.android.client.service.SplitApiFacade;
import io.split.android.client.service.executor.SplitSingleThreadTaskExecutor;
import io.split.android.client.service.executor.SplitTaskExecutionInfo;
import io.split.android.client.service.executor.SplitTaskExecutionListener;
import io.split.android.client.service.executor.SplitTaskExecutor;
import io.split.android.client.service.executor.SplitTaskExecutorImpl;
import io.split.android.client.service.executor.SplitTaskFactory;
import io.split.android.client.service.executor.SplitTaskFactoryImpl;
import io.split.android.client.service.impressions.ImpressionManager;
import io.split.android.client.service.impressions.StrategyImpressionManager;
import io.split.android.client.service.sseclient.sseclient.StreamingComponents;
import io.split.android.client.service.synchronizer.RolloutCacheManagerImpl;
import io.split.android.client.service.synchronizer.SyncManager;
import io.split.android.client.service.synchronizer.Synchronizer;
import io.split.android.client.service.synchronizer.SynchronizerImpl;
Expand Down Expand Up @@ -314,44 +310,34 @@ public void run() {
}
});

// Set up async initialization
final SplitFactoryHelper.Initializer initializer = new SplitFactoryHelper.Initializer(apiToken,
config,
splitTaskFactory,
splitDatabase,
splitCipher,
mEventsManagerCoordinator,
splitTaskExecutor,
splitSingleThreadTaskExecutor,
mStorageContainer,
mSyncManager,
mLifecycleManager);

// Initialize default client
client();
SplitParser mSplitParser = new SplitParser(mStorageContainer.getMySegmentsStorageContainer(), mStorageContainer.getMyLargeSegmentsStorageContainer());
mManager = new SplitManagerImpl(
mStorageContainer.getSplitsStorage(),
new SplitValidatorImpl(), mSplitParser);

Runnable initializer = new Runnable() {
@Override
public void run() {
RolloutCacheManagerImpl rolloutCacheManager = new RolloutCacheManagerImpl(config,
mStorageContainer,
splitTaskFactory.createCleanUpDatabaseTask(System.currentTimeMillis() / 1000),
splitTaskFactory.createEncryptionMigrationTask(apiToken, splitDatabase, config.encryptionEnabled(), splitCipher));

rolloutCacheManager.validateCache(new SplitTaskExecutionListener() {
@Override
public void taskExecuted(@NonNull SplitTaskExecutionInfo taskInfo) {
mEventsManagerCoordinator.notifyInternalEvent(SplitInternalEvent.ENCRYPTION_MIGRATION_DONE);

splitTaskExecutor.resume();
splitSingleThreadTaskExecutor.resume();

mSyncManager.start();
mLifecycleManager.register(mSyncManager);

Logger.i("Android SDK initialized!");
}
});
}
};
new Thread(initializer).start();

if (config.shouldRecordTelemetry()) {
int activeFactoriesCount = mFactoryMonitor.count(mApiKey);
mStorageContainer.getTelemetryStorage().recordActiveFactories(activeFactoriesCount);
mStorageContainer.getTelemetryStorage().recordRedundantFactories(activeFactoriesCount - 1);
}

// Run initializer
new Thread(initializer).start();
}

private static String getFlagsSpec(@Nullable TestingConfig testingConfig) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ public boolean clearAttributes() {

private void submitUpdateTask(PersistentAttributesStorage persistentStorage, Map<String, Object> mInMemoryAttributes) {
if (persistentStorage != null && mSplitTaskExecutor != null && mAttributeTaskFactory != null) {
mSplitTaskExecutor.submit(mAttributeTaskFactory.createAttributeUpdateTask(persistentStorage, mInMemoryAttributes), null);
mSplitTaskExecutor.schedule(mAttributeTaskFactory.createAttributeUpdateTask(persistentStorage, mInMemoryAttributes), 5L, null);
}
}

private void submitClearTask(PersistentAttributesStorage persistentStorage) {
if (persistentStorage != null && mSplitTaskExecutor != null && mAttributeTaskFactory != null) {
mSplitTaskExecutor.submit(mAttributeTaskFactory.createAttributeClearTask(persistentStorage), null);
mSplitTaskExecutor.schedule(mAttributeTaskFactory.createAttributeClearTask(persistentStorage), 5L, null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import io.split.android.client.service.executor.SplitTaskExecutionListener;

interface RolloutCacheManager {
public interface RolloutCacheManager {

void validateCache(SplitTaskExecutionListener listener);
}
58 changes: 49 additions & 9 deletions src/test/java/io/split/android/client/SplitFactoryHelperTest.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package io.split.android.client

import android.content.Context
import io.split.android.client.SplitFactoryHelper.Initializer.Listener
import io.split.android.client.events.EventsManagerCoordinator
import io.split.android.client.events.SplitInternalEvent
import io.split.android.client.lifecycle.SplitLifecycleManager
import io.split.android.client.service.executor.SplitSingleThreadTaskExecutor
import io.split.android.client.service.executor.SplitTaskExecutionInfo
import io.split.android.client.service.executor.SplitTaskExecutionListener
import io.split.android.client.service.executor.SplitTaskExecutor
import io.split.android.client.storage.cipher.EncryptionMigrationTask
import io.split.android.client.storage.db.SplitRoomDatabase
import io.split.android.client.service.executor.SplitTaskType
import io.split.android.client.service.synchronizer.RolloutCacheManager
import io.split.android.client.service.synchronizer.SyncManager
import junit.framework.TestCase.assertEquals
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.any
import org.mockito.Mockito.argThat
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
Expand All @@ -24,12 +30,6 @@ class SplitFactoryHelperTest {

private lateinit var mocks: AutoCloseable

@Mock
private lateinit var splitRoomDatabase: SplitRoomDatabase
@Mock
private lateinit var splitTaskExecutor: SplitTaskExecutor
@Mock
private lateinit var taskListener: SplitTaskExecutionListener
@Mock
private lateinit var context: Context

Expand Down Expand Up @@ -136,4 +136,44 @@ class SplitFactoryHelperTest {
verify(existingPath).renameTo(nonExistingPath)
assertEquals("abcdwxyz", databaseName)
}

@Test
fun `Initializer test`() {
val rolloutCacheManager = mock(RolloutCacheManager::class.java)
val splitTaskExecutionListener = mock(SplitTaskExecutionListener::class.java)

val initializer = SplitFactoryHelper.Initializer(
rolloutCacheManager,
splitTaskExecutionListener
)

initializer.run()

verify(rolloutCacheManager).validateCache(splitTaskExecutionListener)
}

@Test
fun `Initializer Listener test`() {
val eventsManagerCoordinator = mock(EventsManagerCoordinator::class.java)
val taskExecutor = mock(SplitTaskExecutor::class.java)
val singleThreadTaskExecutor = mock(SplitSingleThreadTaskExecutor::class.java)
val syncManager = mock(SyncManager::class.java)
val lifecycleManager = mock(SplitLifecycleManager::class.java)

val listener = Listener(
eventsManagerCoordinator,
taskExecutor,
singleThreadTaskExecutor,
syncManager,
lifecycleManager
)

listener.taskExecuted(SplitTaskExecutionInfo.success(SplitTaskType.GENERIC_TASK))

verify(eventsManagerCoordinator).notifyInternalEvent(SplitInternalEvent.ENCRYPTION_MIGRATION_DONE)
verify(taskExecutor).resume()
verify(singleThreadTaskExecutor).resume()
verify(syncManager).start()
verify(lifecycleManager).register(syncManager)
}
}

0 comments on commit 4532d4a

Please sign in to comment.