Synchronizing high scores between local and server using RxJava
I am trying to sync some data between local records and records on the server.
syncList
is the entry point for the synchronization operation with local records. Inside this method, I call a method syncResultObservable
that returns an Observable with records on the server.
After downloading the records from the server, I use flatmap
to convert the sync result to map<String, List<String>>
by calling syncResult (List<String> local, List<String> server)
. The resulting map
should have 2 keys
"toAdd":List<String>
"toRemove":List<String>
Now I want to perform separate operations on each result.
recordsAddObservable
should add a list from toAdd
(i can do that).
recordsRemoveObservable
should remove add list from toRemove
(could not find a way to perform this operation using the same observable).
recordsAddObservable
The operation toAdd
works fine for me. However, I'm trying to find a way to call recordsRemoveObservable
on the map result without forcing the entire sync operation to run again to remove the case. Below is a small snippet for 'toAdd' entries.
public void syncList(final List<String> localData) {
//fetch the server data
Observable<Map<String, List<String>>> syncResultObservable = serverDataDownloadObservable(userid)
.flatMap(new Func1<String[], Observable<Map<String, List<String>>>>() {
@Override
public Observable<Map<String, List<String>>> call(String[] serverData) {
Map<String, List<String>> map = syncResult(localData, Arrays.asList(serverData));
return Observable.just(map);
}
});
syncResultObservable.flatMap(new Func1<Map<String, List<String>>, Observable<List<String>>>() {
@Override
public Observable<List<String>> call(Map<String, List<String>> stringListMap) {
List<String> toAdd;
toAdd = stringListMap.get("toAdd");
if (toAdd == null || toAdd.isEmpty()) {
toAdd = new ArrayList<String>();
}
return Observable.just(toAdd);
}
}).flatMap(new Func1<List<String>, Observable<Result>>() {
@Override
public Observable<Result> call(List<String> strings) {
if (strings.isEmpty() == false) {
String[] toAdd = strings.toArray(new String[strings.size()]);
Log.i(LogEnum.LogPriority.info, getClass, "syncRecords: will try to add records ", toAdd);
return apis.recordsAddObservable(userid, toAdd);
}
Log.i("Tag", getClass, "syncRecords: no records to add, toAdd);
Log.i("Tag", getClass, "syncRecords: no records need to be added ");
return Observable.just(new Result(null, null));
}
}).subscribeOn(Schedulers.io()).subscribe(new Subscriber<Result>() {
@Override
public void onCompleted() {
//
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Result result) {
onCompleted();
}
});
}
public Map<String, List<String>> syncResult (List<String> local, List<String> server) {
. . .
. . .
Map<String, List<String>> map = new HashMap<>();
map.put("toAdd", toAddList);
map.put("toRemove", toRemoveList);
return map
}
Please let me know if there is an easy way to make individual work of different result sets.
Thanks Big O
source to share
This is how I solved it.
public void syncList(final List<String> localData) {
//fetch the server data
Observable<Map<String, List<String>>> syncResultObservable = serverDataDownloadObservable(userid)
.flatMap(new Func1<String[], Observable<Map<String, List<String>>>>() {
@Override
public Observable<Map<String, List<String>>> call(String[] serverData) {
Map<String, List<String>> map = syncResult(localData, Arrays.asList(serverData));
return Observable.just(map);
}
}).subscribeOn(Schedulers.io())
.subscribe(new Action1<Map<String, List<String>>>() {
@Override
public void call(Map<String, List<String>> stringListMap) {
List<String> toAdd = stringListMap.get("toAdd");
if (toAdd != null && toAdd.isEmpty() == false) {
} else {
addRecords(toAdd);
}
List<String> toRemove = stringListMap.get("toRemove");
if (toRemove != null && toRemove.isEmpty() == false) {
removeRecords(toRemove);
}
}
});
}
source to share
Here's an example that I think does what you want:
- takes a stream of local and server values,
- apply a list to them,
- write them together and apply the difference calculation logic,
- since you decided to use a map with specific keys, we need to flatten it into streams with keys,
- then create groups based on two keys,
- and switch the keys to flatMap to run the asynchronous work needed for each case.
source to share