Skip to content

SyncHelper with RBS storage #746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ba303d8
Persistent storage
gthea Feb 25, 2025
1ade063
WIP
gthea Feb 25, 2025
2b2b424
SqLite persistent storage tests
gthea Feb 25, 2025
e292005
Tests
gthea Feb 25, 2025
bae1f83
Fixes
gthea Feb 25, 2025
c1c96dd
Add exception handling
gthea Feb 25, 2025
ad23322
More tests
gthea Feb 25, 2025
2fc3f2e
Add nullability annotations
gthea Feb 25, 2025
96bca34
Merge branch 'SDKS-9357_baseline' into SDKS-9439_1
gthea Feb 27, 2025
a8bff33
Prep for ParserCommons
gthea Feb 27, 2025
537ed77
Tests for lazy storage provider
gthea Feb 27, 2025
7519aca
Fix impl
gthea Feb 27, 2025
724c681
Storage change & matcher implementation
gthea Feb 27, 2025
2d221fb
Temp parser for RBS storage
gthea Feb 27, 2025
24b8c6b
Fix
gthea Feb 27, 2025
f042de3
Fix test
gthea Feb 27, 2025
cfa0c6c
In RBS matcher test
gthea Feb 27, 2025
0cbde4c
RBS parser
gthea Feb 27, 2025
4ddb4aa
Simplify initialization
gthea Feb 27, 2025
509204e
Fix tests
gthea Feb 27, 2025
83d4550
Merge branch 'SDKS-9357_baseline' into SDKS-9439_3
gthea Feb 28, 2025
2672fbf
WIP
gthea Feb 28, 2025
fa22170
Manual test updates
gthea Mar 5, 2025
0aabcaa
Change mock .json
gthea Mar 5, 2025
d714903
UT migrated
gthea Mar 5, 2025
9f29fb3
WIP tests migration
gthea Mar 5, 2025
7ffc626
Tests migration continued
gthea Mar 5, 2025
c0c380d
Fix
gthea Mar 5, 2025
5cf6449
Merge branch 'SDKS-9357_baseline' into SDKS-9437
gthea Mar 5, 2025
056141a
WIP
gthea Mar 5, 2025
3a6b873
Move storage init
gthea Mar 6, 2025
0d75096
Producer tests
gthea Mar 6, 2025
e4beef9
Merge branch 'SDKS-9357_baseline' into SDKS-9437_2
gthea Mar 6, 2025
738cdc7
Additional test check
gthea Mar 6, 2025
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
20 changes: 0 additions & 20 deletions src/main/java/io/split/android/client/SplitFactoryHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@
import io.split.android.client.storage.events.PersistentEventsStorage;
import io.split.android.client.storage.general.GeneralInfoStorage;
import io.split.android.client.storage.impressions.PersistentImpressionsStorage;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorage;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageImpl;
import io.split.android.client.storage.splits.SplitsStorage;
import io.split.android.client.telemetry.TelemetrySynchronizer;
import io.split.android.client.telemetry.TelemetrySynchronizerImpl;
Expand All @@ -96,8 +94,6 @@
import io.split.android.client.telemetry.storage.TelemetryStorage;
import io.split.android.client.utils.Utils;
import io.split.android.client.utils.logger.Logger;
import io.split.android.engine.experiments.ParserCommons;
import io.split.android.engine.experiments.RuleBasedSegmentParser;

class SplitFactoryHelper {
private static final int DB_MAGIC_CHARS_COUNT = 4;
Expand Down Expand Up @@ -469,22 +465,6 @@ ExecutorService getImpressionsLoggingTaskExecutor() {
new ThreadPoolExecutor.CallerRunsPolicy());
}

@NonNull
static ParserCommons getParserCommons(SplitStorageContainer storageContainer) {
ParserCommons parserCommons = new ParserCommons(
storageContainer.getMySegmentsStorageContainer(),
storageContainer.getMyLargeSegmentsStorageContainer());

RuleBasedSegmentParser ruleBasedSegmentParser = new RuleBasedSegmentParser(parserCommons);

RuleBasedSegmentStorage ruleBasedSegmentStorage =
new RuleBasedSegmentStorageImpl(storageContainer.getPersistentRuleBasedSegmentStorage(), ruleBasedSegmentParser);

parserCommons.setRuleBasedSegmentStorage(ruleBasedSegmentStorage);

return parserCommons;
}

private TelemetryStorage getTelemetryStorage(boolean shouldRecordTelemetry, TelemetryStorage telemetryStorage) {
if (telemetryStorage != null) {
return telemetryStorage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
import io.split.android.client.validators.ValidationErrorInfo;
import io.split.android.client.validators.ValidationMessageLogger;
import io.split.android.client.validators.ValidationMessageLoggerImpl;
import io.split.android.engine.experiments.ParserCommons;
import io.split.android.engine.experiments.SplitParser;

public class SplitFactoryImpl implements SplitFactory {
Expand Down Expand Up @@ -274,10 +273,7 @@ private SplitFactoryImpl(@NonNull String apiToken, @NonNull Key key, @NonNull Sp
streamingComponents.getNotificationProcessor(), streamingComponents.getSseAuthenticator(),
mStorageContainer, mSyncManager, compressionProvider);

ParserCommons parserCommons = SplitFactoryHelper.getParserCommons(mStorageContainer);

// Create SplitParser with ParserCommons
SplitParser splitParser = new SplitParser(parserCommons);
SplitParser splitParser = new SplitParser(mStorageContainer.getParserCommons());

mClientContainer = new SplitClientContainerImpl(
mDefaultClientKey.matchingKey(), this, config, mSyncManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ public List<RuleBasedSegment> getSegments() {

@VisibleForTesting
public static RuleBasedSegmentChange createEmpty() {
return create(-1, -1, new ArrayList<>());
}

@VisibleForTesting
public static RuleBasedSegmentChange create(long since, long till, List<RuleBasedSegment> segments) {
RuleBasedSegmentChange ruleBasedSegmentChange = new RuleBasedSegmentChange();
ruleBasedSegmentChange.segments = new ArrayList<>();
ruleBasedSegmentChange.since = -1;
ruleBasedSegmentChange.till = -1;
ruleBasedSegmentChange.segments = segments;
ruleBasedSegmentChange.since = since;
ruleBasedSegmentChange.till = till;
return ruleBasedSegmentChange;
}
}
11 changes: 11 additions & 0 deletions src/main/java/io/split/android/client/dtos/SplitChange.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
package io.split.android.client.dtos;

import androidx.annotation.VisibleForTesting;

import java.util.List;

public class SplitChange {
public List<Split> splits;
public long since;
public long till;

@VisibleForTesting
public static SplitChange create(long since, long till, List<Split> splits) {
SplitChange splitChange = new SplitChange();
splitChange.since = since;
splitChange.till = till;
splitChange.splits = splits;
return splitChange;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ public RuleBasedSegmentChange getRuleBasedSegmentsChange() {

@VisibleForTesting
public static TargetingRulesChange create(SplitChange splitChange) {
return create(splitChange, RuleBasedSegmentChange.createEmpty());
}

@VisibleForTesting
public static TargetingRulesChange create(SplitChange splitChange, RuleBasedSegmentChange ruleBasedSegmentChange) {
TargetingRulesChange targetingRulesChange = new TargetingRulesChange();
targetingRulesChange.ff = splitChange;
targetingRulesChange.rbs = new RuleBasedSegmentChange();
targetingRulesChange.rbs = ruleBasedSegmentChange;
return targetingRulesChange;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import io.split.android.client.storage.cipher.SplitCipher;
import io.split.android.client.storage.common.SplitStorageContainer;
import io.split.android.client.storage.db.SplitRoomDatabase;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageProducer;
import io.split.android.client.telemetry.storage.TelemetryRuntimeProducer;
import io.split.android.client.telemetry.storage.TelemetryStorage;

Expand Down Expand Up @@ -83,20 +84,23 @@ public SplitTaskFactoryImpl(@NonNull SplitClientConfig splitClientConfig,
mFlagsSpecFromConfig = flagsSpecFromConfig;
mEventsManager = eventsManager;
mSplitChangeProcessor = new SplitChangeProcessor(filters, flagSetsFilter);
RuleBasedSegmentStorageProducer ruleBasedSegmentStorageProducer = mSplitsStorageContainer.getRuleBasedSegmentStorage();

TelemetryStorage telemetryStorage = mSplitsStorageContainer.getTelemetryStorage();
mTelemetryRuntimeProducer = telemetryStorage;
if (testingConfig != null) {
mSplitsSyncHelper = new SplitsSyncHelper(mSplitApiFacade.getSplitFetcher(),
mSplitsStorageContainer.getSplitsStorage(),
mSplitChangeProcessor,
ruleBasedSegmentStorageProducer,
mTelemetryRuntimeProducer,
new ReconnectBackoffCounter(1, testingConfig.getCdnBackoffTime()),
flagsSpecFromConfig);
} else {
mSplitsSyncHelper = new SplitsSyncHelper(mSplitApiFacade.getSplitFetcher(),
mSplitsStorageContainer.getSplitsStorage(),
mSplitChangeProcessor,
ruleBasedSegmentStorageProducer,
mTelemetryRuntimeProducer,
flagsSpecFromConfig);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
import androidx.annotation.VisibleForTesting;

import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import io.split.android.client.dtos.RuleBasedSegment;
import io.split.android.client.dtos.RuleBasedSegmentChange;
import io.split.android.client.dtos.SplitChange;
import io.split.android.client.dtos.Status;
import io.split.android.client.dtos.TargetingRulesChange;
import io.split.android.client.network.SplitHttpHeadersBuilder;
import io.split.android.client.service.ServiceConstants;
Expand All @@ -23,6 +28,7 @@
import io.split.android.client.service.http.HttpStatus;
import io.split.android.client.service.sseclient.BackoffCounter;
import io.split.android.client.service.sseclient.ReconnectBackoffCounter;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageProducer;
import io.split.android.client.storage.splits.SplitsStorage;
import io.split.android.client.telemetry.model.OperationType;
import io.split.android.client.telemetry.storage.TelemetryRuntimeProducer;
Expand All @@ -37,18 +43,21 @@ public class SplitsSyncHelper {
private final HttpFetcher<TargetingRulesChange> mSplitFetcher;
private final SplitsStorage mSplitsStorage;
private final SplitChangeProcessor mSplitChangeProcessor;
private final RuleBasedSegmentStorageProducer mRuleBasedSegmentStorage;
private final TelemetryRuntimeProducer mTelemetryRuntimeProducer;
private final BackoffCounter mBackoffCounter;
private final String mFlagsSpec;

public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
@NonNull SplitsStorage splitsStorage,
@NonNull SplitChangeProcessor splitChangeProcessor,
@NonNull RuleBasedSegmentStorageProducer ruleBasedSegmentStorage,
@NonNull TelemetryRuntimeProducer telemetryRuntimeProducer,
@Nullable String flagsSpec) {
this(splitFetcher,
splitsStorage,
splitChangeProcessor,
ruleBasedSegmentStorage,
telemetryRuntimeProducer,
new ReconnectBackoffCounter(1, ON_DEMAND_FETCH_BACKOFF_MAX_WAIT),
flagsSpec);
Expand All @@ -58,12 +67,14 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
@NonNull SplitsStorage splitsStorage,
@NonNull SplitChangeProcessor splitChangeProcessor,
@NonNull RuleBasedSegmentStorageProducer ruleBasedSegmentStorage,
@NonNull TelemetryRuntimeProducer telemetryRuntimeProducer,
@NonNull BackoffCounter backoffCounter,
@Nullable String flagsSpec) {
mSplitFetcher = checkNotNull(splitFetcher);
mSplitsStorage = checkNotNull(splitsStorage);
mSplitChangeProcessor = checkNotNull(splitChangeProcessor);
mRuleBasedSegmentStorage = checkNotNull(ruleBasedSegmentStorage);
mTelemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer);
mBackoffCounter = checkNotNull(backoffCounter);
mFlagsSpec = flagsSpec;
Expand Down Expand Up @@ -155,8 +166,9 @@ private long fetchUntil(long till, boolean clearBeforeUpdate, boolean avoidCache
}

TargetingRulesChange targetingRulesChange = fetchSplits(changeNumber, avoidCache, withCdnByPass);
SplitChange splitChange = targetingRulesChange.getFeatureFlagsChange(); // TODO
updateStorage(shouldClearBeforeUpdate, splitChange);
SplitChange splitChange = targetingRulesChange.getFeatureFlagsChange();
RuleBasedSegmentChange ruleBasedSegmentChange = targetingRulesChange.getRuleBasedSegmentsChange();
updateStorage(shouldClearBeforeUpdate, splitChange, ruleBasedSegmentChange);
shouldClearBeforeUpdate = false;

newTill = splitChange.till;
Expand All @@ -180,11 +192,27 @@ private TargetingRulesChange fetchSplits(long till, boolean avoidCache, boolean
return mSplitFetcher.execute(params, getHeaders(avoidCache));
}

private void updateStorage(boolean clearBeforeUpdate, SplitChange splitChange) {
private void updateStorage(boolean clearBeforeUpdate, SplitChange splitChange, RuleBasedSegmentChange ruleBasedSegmentChange) {
if (clearBeforeUpdate) {
mSplitsStorage.clear();
mRuleBasedSegmentStorage.clear();
}
mSplitsStorage.update(mSplitChangeProcessor.process(splitChange));
updateRbsStorage(ruleBasedSegmentChange);
}

private void updateRbsStorage(RuleBasedSegmentChange ruleBasedSegmentChange) {
long changeNumber = ruleBasedSegmentChange.getTill();
Set<RuleBasedSegment> toAdd = new HashSet<>();
Set<RuleBasedSegment> toRemove = new HashSet<>();
for (RuleBasedSegment segment : ruleBasedSegmentChange.getSegments()) {
if (segment.getStatus() == Status.ACTIVE) {
toAdd.add(segment);
} else {
toRemove.add(segment);
}
}
mRuleBasedSegmentStorage.update(toAdd, toRemove, changeNumber);
}

private void logError(String message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.split.android.client.service.splits.SplitChangeProcessor;
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.telemetry.storage.TelemetryStorage;
import io.split.android.client.utils.logger.Logger;
Expand Down Expand Up @@ -37,12 +38,14 @@ SplitTask getTask() {
try {
SplitsStorage splitsStorage = mStorageProvider.provideSplitsStorage();
TelemetryStorage telemetryStorage = mStorageProvider.provideTelemetryStorage();
RuleBasedSegmentStorageProducer ruleBasedSegmentStorageProducer = mStorageProvider.provideRuleBasedSegmentStorage();
String splitsFilterQueryString = splitsStorage.getSplitsFilterQueryString();

SplitsSyncHelper splitsSyncHelper = mSplitsSyncHelperProvider.provideSplitsSyncHelper(
mFetcherProvider.provideFetcher(splitsFilterQueryString),
splitsStorage,
mSplitChangeProcessor,
ruleBasedSegmentStorageProducer,
telemetryStorage,
mFlagsSpec);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
package io.split.android.client.service.workmanager.splits;

import io.split.android.client.storage.cipher.SplitCipher;
import io.split.android.client.storage.cipher.SplitCipherFactory;
import io.split.android.client.storage.db.SplitRoomDatabase;
import io.split.android.client.storage.db.StorageFactory;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageProducer;
import io.split.android.client.storage.splits.SplitsStorage;
import io.split.android.client.telemetry.storage.TelemetryStorage;

class StorageProvider {

private final SplitRoomDatabase mDatabase;
private final String mApiKey;
private final boolean mEncryptionEnabled;
private final boolean mShouldRecordTelemetry;
private final SplitCipher mCipher;

StorageProvider(SplitRoomDatabase database, String apiKey, boolean encryptionEnabled, boolean shouldRecordTelemetry) {
mDatabase = database;
mApiKey = apiKey;
mEncryptionEnabled = encryptionEnabled;
mCipher = SplitCipherFactory.create(apiKey, encryptionEnabled);
mShouldRecordTelemetry = shouldRecordTelemetry;
}

SplitsStorage provideSplitsStorage() {
SplitsStorage splitsStorageForWorker = StorageFactory.getSplitsStorageForWorker(mDatabase, mApiKey, mEncryptionEnabled);
SplitsStorage splitsStorageForWorker = StorageFactory.getSplitsStorage(mDatabase, mCipher);
splitsStorageForWorker.loadLocal(); // call loadLocal to populate storage with DB data

return splitsStorageForWorker;
Expand All @@ -29,4 +30,11 @@ SplitsStorage provideSplitsStorage() {
TelemetryStorage provideTelemetryStorage() {
return StorageFactory.getTelemetryStorage(mShouldRecordTelemetry);
}

RuleBasedSegmentStorageProducer provideRuleBasedSegmentStorage() {
RuleBasedSegmentStorageProducer ruleBasedSegmentStorageForWorker = StorageFactory.getRuleBasedSegmentStorageForWorker(mDatabase, mCipher);
ruleBasedSegmentStorageForWorker.loadLocal(); // call loadLocal to populate storage with DB data

return ruleBasedSegmentStorageForWorker;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@
import io.split.android.client.service.http.HttpFetcher;
import io.split.android.client.service.splits.SplitChangeProcessor;
import io.split.android.client.service.splits.SplitsSyncHelper;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageProducer;
import io.split.android.client.storage.splits.SplitsStorage;
import io.split.android.client.telemetry.storage.TelemetryStorage;

class SyncHelperProvider {

SplitsSyncHelper provideSplitsSyncHelper(HttpFetcher<TargetingRulesChange> splitsFetcher, SplitsStorage splitsStorage,
SplitChangeProcessor mSplitChangeProcessor,
SplitsSyncHelper provideSplitsSyncHelper(HttpFetcher<TargetingRulesChange> splitsFetcher,
SplitsStorage splitsStorage,
SplitChangeProcessor splitChangeProcessor,
RuleBasedSegmentStorageProducer ruleBasedSegmentStorage,
TelemetryStorage telemetryStorage,
String mFlagsSpec) {
return new SplitsSyncHelper(splitsFetcher, splitsStorage,
mSplitChangeProcessor,
splitChangeProcessor,
ruleBasedSegmentStorage,
telemetryStorage,
mFlagsSpec);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
import io.split.android.client.storage.mysegments.MySegmentsStorage;
import io.split.android.client.storage.mysegments.MySegmentsStorageContainer;
import io.split.android.client.storage.rbs.PersistentRuleBasedSegmentStorage;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorage;
import io.split.android.client.storage.rbs.RuleBasedSegmentStorageImpl;
import io.split.android.client.storage.splits.PersistentSplitsStorage;
import io.split.android.client.storage.splits.SplitsStorage;
import io.split.android.client.telemetry.storage.TelemetryStorage;
import io.split.android.engine.experiments.ParserCommons;
import io.split.android.engine.experiments.RuleBasedSegmentParser;

public class SplitStorageContainer {

Expand All @@ -39,7 +43,8 @@ public class SplitStorageContainer {
private final PersistentImpressionsUniqueStorage mPersistentImpressionsUniqueStorage;
private final PersistentImpressionsObserverCacheStorage mPersistentImpressionsObserverCacheStorage;
private final GeneralInfoStorage mGeneralInfoStorage;
private final PersistentRuleBasedSegmentStorage mPersistentRuleBasedSegmentStorage;
private final ParserCommons mParserCommons;
private final RuleBasedSegmentStorage mRuleBasedSegmentStorage;

public SplitStorageContainer(@NonNull SplitsStorage splitStorage,
@NonNull MySegmentsStorageContainer mySegmentsStorageContainer,
Expand Down Expand Up @@ -73,7 +78,10 @@ public SplitStorageContainer(@NonNull SplitsStorage splitStorage,
mPersistentImpressionsUniqueStorage = checkNotNull(persistentImpressionsUniqueStorage);
mPersistentImpressionsObserverCacheStorage = checkNotNull(persistentImpressionsObserverCacheStorage);
mGeneralInfoStorage = checkNotNull(generalInfoStorage);
mPersistentRuleBasedSegmentStorage = checkNotNull(persistentRuleBasedSegmentStorage);
mParserCommons = new ParserCommons(
mySegmentsStorageContainer,
myLargeSegmentsStorageContainer);
mRuleBasedSegmentStorage = new RuleBasedSegmentStorageImpl(persistentRuleBasedSegmentStorage, new RuleBasedSegmentParser(mParserCommons));
}

public SplitsStorage getSplitsStorage() {
Expand Down Expand Up @@ -148,7 +156,11 @@ public GeneralInfoStorage getGeneralInfoStorage() {
return mGeneralInfoStorage;
}

public PersistentRuleBasedSegmentStorage getPersistentRuleBasedSegmentStorage() {
return mPersistentRuleBasedSegmentStorage;
public ParserCommons getParserCommons() {
return mParserCommons;
}

public RuleBasedSegmentStorage getRuleBasedSegmentStorage() {
return mRuleBasedSegmentStorage;
}
}
Loading
Loading