Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ apply from: 'spec.gradle'
apply from: 'jacoco.gradle'

ext {
splitVersion = '5.4.0'
splitVersion = '5.4.1-alpha.1'
jacocoVersion = '0.8.8'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ public ImpressionsRecorderTask createImpressionsRecorderTask() {

@Override
public SplitsSyncTask createSplitsSyncTask(boolean checkCacheExpiration) {
return SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorageContainer.getSplitsStorage(),
mSplitsStorageContainer.getRuleBasedSegmentStorage(),
return SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorageContainer.getGeneralInfoStorage(),
mSplitsFilterQueryStringFromConfig, mEventsManager, mSplitsStorageContainer.getTelemetryStorage());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class SplitsSyncHelper {
private final SplitChangeProcessor mSplitChangeProcessor;
private final RuleBasedSegmentChangeProcessor mRuleBasedSegmentChangeProcessor;
private final RuleBasedSegmentStorageProducer mRuleBasedSegmentStorage;
private final GeneralInfoStorage mGeneralInfoStorage;
private final TelemetryRuntimeProducer mTelemetryRuntimeProducer;
private final BackoffCounter mBackoffCounter;
private final OutdatedSplitProxyHandler mOutdatedSplitProxyHandler;
Expand Down Expand Up @@ -113,6 +114,7 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
mRuleBasedSegmentStorage = checkNotNull(ruleBasedSegmentStorage);
mTelemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer);
mBackoffCounter = checkNotNull(backoffCounter);
mGeneralInfoStorage = checkNotNull(generalInfoStorage);
mOutdatedSplitProxyHandler = new OutdatedSplitProxyHandler(flagsSpec, forBackgroundSync, generalInfoStorage, proxyCheckIntervalMillis);
}

Expand Down Expand Up @@ -225,8 +227,8 @@ private SinceChangeNumbers fetchUntil(SinceChangeNumbers till, boolean clearBefo

SinceChangeNumbers newTill = till;
while (true) {
long changeNumber = (resetChangeNumber) ? -1 : mSplitsStorage.getTill();
long rbsChangeNumber = (resetChangeNumber) ? -1 : mRuleBasedSegmentStorage.getChangeNumber();
long changeNumber = (resetChangeNumber) ? -1 : mGeneralInfoStorage.getFlagsChangeNumber();
long rbsChangeNumber = (resetChangeNumber) ? -1 : mGeneralInfoStorage.getRbsChangeNumber();
resetChangeNumber = false;
if ((newTill.getFlagsSince() < changeNumber) && ((newTill.getRbsSince() == null) || (newTill.getRbsSince() < rbsChangeNumber))) {
return new SinceChangeNumbers(changeNumber, rbsChangeNumber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,15 @@
import io.split.android.client.service.executor.SplitTaskExecutionInfo;
import io.split.android.client.service.executor.SplitTaskExecutionStatus;
import io.split.android.client.service.synchronizer.SplitsChangeChecker;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageProducer;
import io.split.android.client.storage.splits.SplitsStorage;
import io.split.android.client.storage.general.GeneralInfoStorage;
import io.split.android.client.telemetry.model.OperationType;
import io.split.android.client.telemetry.storage.TelemetryRuntimeProducer;

public class SplitsSyncTask implements SplitTask {

private final String mSplitsFilterQueryStringFromConfig;

private final SplitsStorage mSplitsStorage;
private final RuleBasedSegmentStorageProducer mRuleBasedSegmentStorage;
private final GeneralInfoStorage mGeneralInfoStorage;
private final SplitsSyncHelper mSplitsSyncHelper;
@Nullable
private final ISplitEventsManager mEventsManager; // Should only be null on background sync
Expand All @@ -31,33 +29,29 @@ public class SplitsSyncTask implements SplitTask {
private final int mOnDemandFetchBackoffMaxRetries;

public static SplitsSyncTask build(@NonNull SplitsSyncHelper splitsSyncHelper,
@NonNull SplitsStorage splitsStorage,
@NonNull RuleBasedSegmentStorageProducer ruleBasedSegmentStorage,
@NonNull GeneralInfoStorage generalInfoStorage,
String splitsFilterQueryString,
@NonNull ISplitEventsManager eventsManager,
@NonNull TelemetryRuntimeProducer telemetryRuntimeProducer) {
return new SplitsSyncTask(splitsSyncHelper, splitsStorage, ruleBasedSegmentStorage, splitsFilterQueryString, telemetryRuntimeProducer, eventsManager, ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES);
return new SplitsSyncTask(splitsSyncHelper, generalInfoStorage, splitsFilterQueryString, telemetryRuntimeProducer, eventsManager, ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES);
}

public static SplitTask buildForBackground(@NonNull SplitsSyncHelper splitsSyncHelper,
@NonNull SplitsStorage splitsStorage,
@NonNull RuleBasedSegmentStorageProducer ruleBasedSegmentStorage,
@NonNull GeneralInfoStorage generalInfoStorage,
String splitsFilterQueryString,
@NonNull TelemetryRuntimeProducer telemetryRuntimeProducer) {
return new SplitsSyncTask(splitsSyncHelper, splitsStorage, ruleBasedSegmentStorage, splitsFilterQueryString, telemetryRuntimeProducer, null, 1);
return new SplitsSyncTask(splitsSyncHelper, generalInfoStorage, splitsFilterQueryString, telemetryRuntimeProducer, null, 1);
}

private SplitsSyncTask(@NonNull SplitsSyncHelper splitsSyncHelper,
@NonNull SplitsStorage splitsStorage,
@NonNull RuleBasedSegmentStorageProducer ruleBasedSegmentStorage,
@NonNull GeneralInfoStorage generalInfoStorage,
String splitsFilterQueryString,
@NonNull TelemetryRuntimeProducer telemetryRuntimeProducer,
@Nullable ISplitEventsManager eventsManager,
int onDemandFetchBackoffMaxRetries) {

mSplitsStorage = checkNotNull(splitsStorage);
mSplitsSyncHelper = checkNotNull(splitsSyncHelper);
mRuleBasedSegmentStorage = checkNotNull(ruleBasedSegmentStorage);
mGeneralInfoStorage = checkNotNull(generalInfoStorage);
mSplitsFilterQueryStringFromConfig = splitsFilterQueryString;
mEventsManager = eventsManager;
mChangeChecker = new SplitsChangeChecker();
Expand All @@ -68,13 +62,13 @@ private SplitsSyncTask(@NonNull SplitsSyncHelper splitsSyncHelper,
@Override
@NonNull
public SplitTaskExecutionInfo execute() {
long storedChangeNumber = mSplitsStorage.getTill();
long storedRbsChangeNumber = mRuleBasedSegmentStorage.getChangeNumber();
long storedChangeNumber = mGeneralInfoStorage.getFlagsChangeNumber();
long storedRbsChangeNumber = mGeneralInfoStorage.getRbsChangeNumber();

boolean splitsFilterHasChanged = splitsFilterHasChanged(mSplitsStorage.getSplitsFilterQueryString());
boolean splitsFilterHasChanged = splitsFilterHasChanged(mGeneralInfoStorage.getSplitsFilterQueryString());

if (splitsFilterHasChanged) {
mSplitsStorage.updateSplitsFilterQueryString(mSplitsFilterQueryStringFromConfig);
mGeneralInfoStorage.setSplitsFilterQueryString(mSplitsFilterQueryStringFromConfig);
storedChangeNumber = -1;
}

Expand All @@ -95,7 +89,7 @@ public SplitTaskExecutionInfo execute() {
private void notifyInternalEvent(long storedChangeNumber) {
if (mEventsManager != null) {
SplitInternalEvent event = SplitInternalEvent.SPLITS_FETCHED;
if (mChangeChecker.changeNumberIsNewer(storedChangeNumber, mSplitsStorage.getTill())) {
if (mChangeChecker.changeNumberIsNewer(storedChangeNumber, mGeneralInfoStorage.getFlagsChangeNumber())) {
event = SplitInternalEvent.SPLITS_UPDATED;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ SplitTask getTask() {
mFlagsSpec);

return SplitsSyncTask.buildForBackground(splitsSyncHelper,
splitsStorage,
ruleBasedSegmentStorageProducer,
generalInfoStorage,
splitsFilterQueryString,
telemetryStorage);
} catch (URISyntaxException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import androidx.annotation.NonNull;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -30,8 +32,7 @@
import io.split.android.client.service.http.HttpFetcherException;
import io.split.android.client.service.splits.SplitsSyncHelper;
import io.split.android.client.service.splits.SplitsSyncTask;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageProducer;
import io.split.android.client.storage.splits.SplitsStorage;
import io.split.android.client.storage.general.GeneralInfoStorage;
import io.split.android.client.telemetry.model.OperationType;
import io.split.android.client.telemetry.storage.TelemetryRuntimeProducer;
import io.split.android.helpers.FileHelper;
Expand All @@ -40,10 +41,9 @@ public class SplitSyncTaskTest {

private static final long OLD_TIMESTAMP = 1546300800L; //2019-01-01

SplitsStorage mSplitsStorage;
SplitChange mSplitChange = null;
SplitsSyncHelper mSplitsSyncHelper;
RuleBasedSegmentStorageProducer mRuleBasedSegmentStorage;
private GeneralInfoStorage mGeneralInfoStorage;

SplitsSyncTask mTask;
String mQueryString = "qs=1";
Expand All @@ -56,10 +56,9 @@ public class SplitSyncTaskTest {
public void setup() {
mTelemetryRuntimeProducer = mock(TelemetryRuntimeProducer.class);

mSplitsStorage = mock(SplitsStorage.class);
mSplitsSyncHelper = mock(SplitsSyncHelper.class);
mEventsManager = mock(SplitEventsManager.class);
mRuleBasedSegmentStorage = mock(RuleBasedSegmentStorageProducer.class);
mGeneralInfoStorage = mock(GeneralInfoStorage.class);

when(mSplitsSyncHelper.sync(notNull(), anyBoolean(), anyBoolean(), eq(ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES))).thenReturn(SplitTaskExecutionInfo.success(SplitTaskType.SPLIT_KILL));

Expand All @@ -72,12 +71,12 @@ public void correctExecution() throws HttpFetcherException {
// Querystring is the same, so no clear sould be called
// And updateTimestamp is 0
// Retry is off, so splitSyncHelper.sync should be called
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorage, mRuleBasedSegmentStorage,
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mGeneralInfoStorage,
mQueryString, mEventsManager, mTelemetryRuntimeProducer);
when(mSplitsStorage.getTill()).thenReturn(-1L);
when(mRuleBasedSegmentStorage.getChangeNumber()).thenReturn(-1L);
when(mSplitsStorage.getUpdateTimestamp()).thenReturn(0L);
when(mSplitsStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
when(mGeneralInfoStorage.getFlagsChangeNumber()).thenReturn(-1L);
when(mGeneralInfoStorage.getRbsChangeNumber()).thenReturn(-1L);
when(mGeneralInfoStorage.getSplitsUpdateTimestamp()).thenReturn(0L);
when(mGeneralInfoStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);

mTask.execute();

Expand All @@ -93,34 +92,33 @@ public void cleanSplitsWhenQueryStringHasChanged() throws HttpFetcherException {
String otherQs = "q=other";
Map<String, Object> params = new HashMap<>();
params.put("since", 100L);
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorage, mRuleBasedSegmentStorage,
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mGeneralInfoStorage,
otherQs, mEventsManager, mTelemetryRuntimeProducer);
when(mSplitsStorage.getTill()).thenReturn(100L);
when(mRuleBasedSegmentStorage.getChangeNumber()).thenReturn(200L);
when(mSplitsStorage.getUpdateTimestamp()).thenReturn(1111L);
when(mSplitsStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
when(mGeneralInfoStorage.getFlagsChangeNumber()).thenReturn(100L);
when(mGeneralInfoStorage.getRbsChangeNumber()).thenReturn(200L);
when(mGeneralInfoStorage.getSplitsUpdateTimestamp()).thenReturn(1111L);
when(mGeneralInfoStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);

mTask.execute();

verify(mSplitsSyncHelper, times(1)).sync(argThat(argument -> argument.getFlagsSince() == -1 && argument.getRbsSince() == 200), eq(true), eq(true), eq(ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES));
verify(mSplitsStorage, times(1)).updateSplitsFilterQueryString(otherQs);
verify(mGeneralInfoStorage, times(1)).setSplitsFilterQueryString(otherQs);
}

@Test
public void noClearSplitsWhenQueryStringHasNotChanged() throws HttpFetcherException {
// Splits have to be cleared when query string on db is != than current one on current sdk client instance
// Setting up cache not expired

mTask = SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorage, mRuleBasedSegmentStorage,
mQueryString, mEventsManager, mTelemetryRuntimeProducer);
when(mSplitsStorage.getTill()).thenReturn(100L);
when(mSplitsStorage.getUpdateTimestamp()).thenReturn(1111L);
when(mSplitsStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
mTask = buildSplitsSyncTask();
when(mGeneralInfoStorage.getFlagsChangeNumber()).thenReturn(100L);
when(mGeneralInfoStorage.getSplitsUpdateTimestamp()).thenReturn(1111L);
when(mGeneralInfoStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);

mTask.execute();

verify(mSplitsSyncHelper, times(1)).sync(argThat(argument -> argument.getFlagsSince() == 100L), eq(false), eq(false), eq(ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES));
verify(mSplitsStorage, never()).updateSplitsFilterQueryString(anyString());
verify(mGeneralInfoStorage, never()).setSplitsFilterQueryString(anyString());
}

@Test
Expand All @@ -129,11 +127,10 @@ public void splitUpdatedNotified() throws HttpFetcherException {
// Querystring is the same, so no clear sould be called
// And updateTimestamp is 0
// Retry is off, so splitSyncHelper.sync should be called
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorage, mRuleBasedSegmentStorage,
mQueryString, mEventsManager, mTelemetryRuntimeProducer);
when(mSplitsStorage.getTill()).thenReturn(-1L).thenReturn(100L);
when(mSplitsStorage.getUpdateTimestamp()).thenReturn(0L);
when(mSplitsStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
mTask = buildSplitsSyncTask();
when(mGeneralInfoStorage.getFlagsChangeNumber()).thenReturn(-1L).thenReturn(100L);
when(mGeneralInfoStorage.getSplitsUpdateTimestamp()).thenReturn(0L);
when(mGeneralInfoStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
when(mSplitsSyncHelper.sync(any(), anyBoolean(), anyBoolean(), eq(ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES))).thenReturn(SplitTaskExecutionInfo.success(SplitTaskType.SPLITS_SYNC));

mTask.execute();
Expand All @@ -147,11 +144,10 @@ public void splitFetchdNotified() throws HttpFetcherException {
// Querystring is the same, so no clear sould be called
// And updateTimestamp is 0
// Retry is off, so splitSyncHelper.sync should be called
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorage, mRuleBasedSegmentStorage,
mQueryString, mEventsManager, mTelemetryRuntimeProducer);
when(mSplitsStorage.getTill()).thenReturn(100L);
when(mSplitsStorage.getUpdateTimestamp()).thenReturn(0L);
when(mSplitsStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
mTask = buildSplitsSyncTask();
when(mGeneralInfoStorage.getFlagsChangeNumber()).thenReturn(100L);
when(mGeneralInfoStorage.getSplitsUpdateTimestamp()).thenReturn(0L);
when(mGeneralInfoStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
when(mSplitsSyncHelper.sync(any(), anyBoolean(), anyBoolean(), eq(ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES))).thenReturn(SplitTaskExecutionInfo.success(SplitTaskType.SPLITS_SYNC));

mTask.execute();
Expand All @@ -161,11 +157,10 @@ public void splitFetchdNotified() throws HttpFetcherException {

@Test
public void syncIsTrackedInTelemetry() {
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorage, mRuleBasedSegmentStorage,
mQueryString, mEventsManager, mTelemetryRuntimeProducer);
when(mSplitsStorage.getTill()).thenReturn(100L);
when(mSplitsStorage.getUpdateTimestamp()).thenReturn(0L);
when(mSplitsStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
mTask = buildSplitsSyncTask();
when(mGeneralInfoStorage.getFlagsChangeNumber()).thenReturn(100L);
when(mGeneralInfoStorage.getSplitsUpdateTimestamp()).thenReturn(0L);
when(mGeneralInfoStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
when(mSplitsSyncHelper.sync(any(), anyBoolean(), anyBoolean(), eq(ServiceConstants.ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES))).thenReturn(SplitTaskExecutionInfo.success(SplitTaskType.SPLITS_SYNC));

mTask.execute();
Expand All @@ -175,20 +170,25 @@ public void syncIsTrackedInTelemetry() {

@Test
public void recordSuccessInTelemetry() {
mTask = SplitsSyncTask.build(mSplitsSyncHelper, mSplitsStorage, mRuleBasedSegmentStorage,
mQueryString, mEventsManager, mTelemetryRuntimeProducer);
when(mSplitsStorage.getTill()).thenReturn(-1L);
when(mSplitsStorage.getUpdateTimestamp()).thenReturn(0L);
when(mSplitsStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);
mTask = buildSplitsSyncTask();
when(mGeneralInfoStorage.getFlagsChangeNumber()).thenReturn(-1L);
when(mGeneralInfoStorage.getSplitsUpdateTimestamp()).thenReturn(0L);
when(mGeneralInfoStorage.getSplitsFilterQueryString()).thenReturn(mQueryString);

mTask.execute();

verify(mTelemetryRuntimeProducer).recordSuccessfulSync(eq(OperationType.SPLITS), longThat(arg -> arg > 0));
}

@NonNull
private SplitsSyncTask buildSplitsSyncTask() {
return SplitsSyncTask.build(mSplitsSyncHelper, mGeneralInfoStorage,
mQueryString, mEventsManager, mTelemetryRuntimeProducer);
}

@After
public void tearDown() {
reset(mSplitsStorage);
reset(mGeneralInfoStorage);
}

private void loadSplitChanges() {
Expand Down
Loading
Loading