Skip to content

Commit bb273eb

Browse files
ilgazermaskaravivek
authored andcommitted
Migrated logEvents to retrofit (#3087)
* Switched wikimedia-android-data-client for new features * Added UserCLient and UserInterface * Migrated ContributionsSyncAdapter to UserClient Fixed sync related bugs * Removed unused code * Removed unused code * Updated wikimedia-android-data-client to new version
1 parent 386d087 commit bb273eb

File tree

8 files changed

+90
-132
lines changed

8 files changed

+90
-132
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ dependencies {
3131
implementation 'com.facebook.fresco:fresco:1.13.0'
3232
implementation 'com.drewnoakes:metadata-extractor:2.11.0'
3333
implementation 'org.apache.commons:commons-lang3:3.8.1'
34-
implementation 'com.dmitrybrant:wikimedia-android-data-client:0.0.25'
34+
implementation 'com.github.ilgazer:wikimedia-android-data-client:f65809ee2c'
3535

3636
// UI
3737
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar'

app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ public Contribution(Uri localUri, String imageUrl, String filename, String descr
9292
this.dateCreatedSource = "";
9393
}
9494

95+
public Contribution(Uri localUri, String imageUrl, String filename, String description, long dataLength,
96+
Date dateCreated, Date dateUploaded, String creator, String editSummary, String decimalCoords, int state) {
97+
super(localUri, imageUrl, filename, description, dataLength, dateCreated, dateUploaded, creator);
98+
this.decimalCoords = decimalCoords;
99+
this.editSummary = editSummary;
100+
this.dateCreatedSource = "";
101+
this.state=state;
102+
}
103+
95104
public Contribution(Parcel in) {
96105
super(in);
97106
contentUri = in.readParcelable(Uri.class.getClassLoader());
Lines changed: 25 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.free.nrw.commons.contributions;
22

33
import android.accounts.Account;
4+
import android.annotation.SuppressLint;
45
import android.content.AbstractThreadedSyncAdapter;
56
import android.content.ContentProviderClient;
67
import android.content.ContentValues;
@@ -11,6 +12,8 @@
1112
import android.os.RemoteException;
1213
import android.text.TextUtils;
1314

15+
import org.wikipedia.dataclient.mwapi.MwQueryLogEvent;
16+
import org.wikipedia.dataclient.mwapi.MwQueryResult;
1417
import org.wikipedia.util.DateUtil;
1518

1619
import java.io.IOException;
@@ -26,6 +29,7 @@
2629
import fr.free.nrw.commons.kvstore.JsonKvStore;
2730
import fr.free.nrw.commons.mwapi.LogEventResult;
2831
import fr.free.nrw.commons.mwapi.MediaWikiApi;
32+
import fr.free.nrw.commons.mwapi.UserClient;
2933
import timber.log.Timber;
3034

3135
import static fr.free.nrw.commons.contributions.Contribution.STATE_COMPLETED;
@@ -44,8 +48,8 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
4448
// into the app, rather than the user's setting. Also see Github issue #52.
4549
public static final int ABSOLUTE_CONTRIBUTIONS_LOAD_LIMIT = 500;
4650

47-
@SuppressWarnings("WeakerAccess")
48-
@Inject MediaWikiApi mwApi;
51+
@Inject
52+
UserClient userClient;
4953
@Inject
5054
@Named("default_preferences")
5155
JsonKvStore defaultKvStore;
@@ -58,24 +62,19 @@ private boolean fileExists(ContentProviderClient client, String filename) {
5862
if (filename == null) {
5963
return false;
6064
}
61-
Cursor cursor = null;
62-
try {
63-
cursor = client.query(BASE_URI,
64-
existsQuery,
65-
existsSelection,
66-
new String[]{filename},
67-
""
68-
);
65+
try (Cursor cursor = client.query(BASE_URI,
66+
existsQuery,
67+
existsSelection,
68+
new String[]{filename},
69+
""
70+
)) {
6971
return cursor != null && cursor.getCount() != 0;
7072
} catch (RemoteException e) {
7173
throw new RuntimeException(e);
72-
} finally {
73-
if (cursor != null) {
74-
cursor.close();
75-
}
7674
}
7775
}
7876

77+
@SuppressLint("CheckResult")
7978
@Override
8079
public void onPerformSync(Account account, Bundle bundle, String authority,
8180
ContentProviderClient contentProviderClient, SyncResult syncResult) {
@@ -84,71 +83,20 @@ public void onPerformSync(Account account, Bundle bundle, String authority,
8483
.getApplicationContext())
8584
.getCommonsApplicationComponent()
8685
.inject(this);
87-
// This code is fraught with possibilities of race conditions, but lalalalala I can't hear you!
86+
// This code is(was?) fraught with possibilities of race conditions, but lalalalala I can't hear you!
8887
String user = account.name;
89-
String lastModified = defaultKvStore.getString("lastSyncTimestamp", "");
90-
Date curTime = new Date();
91-
LogEventResult result;
92-
Boolean done = false;
93-
String queryContinue = null;
9488
ContributionDao contributionDao = new ContributionDao(() -> contentProviderClient);
95-
while (!done) {
96-
97-
try {
98-
result = mwApi.logEvents(user, lastModified, queryContinue, ABSOLUTE_CONTRIBUTIONS_LOAD_LIMIT);
99-
} catch (IOException e) {
100-
// There isn't really much we can do, eh?
101-
// FIXME: Perhaps add EventLogging?
102-
syncResult.stats.numIoExceptions += 1; // Not sure if this does anything. Shitty docs
103-
Timber.d("Syncing failed due to %s", e);
104-
return;
105-
}
106-
Timber.d("Last modified at %s", lastModified);
107-
108-
List<LogEventResult.LogEvent> logEvents = result.getLogEvents();
109-
Timber.d("%d results!", logEvents.size());
110-
ArrayList<ContentValues> imageValues = new ArrayList<>();
111-
for (LogEventResult.LogEvent image : logEvents) {
112-
if (image.isDeleted()) {
113-
// means that this upload was deleted.
114-
continue;
115-
}
116-
String filename = image.getFilename();
117-
if (fileExists(contentProviderClient, filename)) {
118-
Timber.d("Skipping %s", filename);
119-
continue;
120-
}
121-
Date dateUpdated = image.getDateUpdated();
122-
Contribution contrib = new Contribution(null, null, filename,
123-
"", -1, dateUpdated, dateUpdated, user,
124-
"", "");
125-
contrib.setState(STATE_COMPLETED);
126-
imageValues.add(contributionDao.toContentValues(contrib));
127-
128-
if (imageValues.size() % COMMIT_THRESHOLD == 0) {
129-
try {
130-
contentProviderClient.bulkInsert(BASE_URI, imageValues.toArray(EMPTY));
131-
} catch (RemoteException e) {
132-
throw new RuntimeException(e);
133-
}
134-
imageValues.clear();
135-
}
136-
}
137-
138-
if (imageValues.size() != 0) {
139-
try {
140-
contentProviderClient.bulkInsert(BASE_URI, imageValues.toArray(EMPTY));
141-
} catch (RemoteException e) {
142-
throw new RuntimeException(e);
143-
}
144-
}
145-
146-
queryContinue = result.getQueryContinue();
147-
if (TextUtils.isEmpty(queryContinue)) {
148-
done = true;
149-
}
150-
}
151-
defaultKvStore.putString("lastSyncTimestamp", DateUtil.iso8601DateFormat(curTime));
89+
userClient.logEvents(user)
90+
.doOnNext(mwQueryLogEvent->Timber.d("Received image %s", mwQueryLogEvent.title() ))
91+
.filter(mwQueryLogEvent -> !mwQueryLogEvent.isDeleted())
92+
.filter(mwQueryLogEvent -> !fileExists(contentProviderClient, mwQueryLogEvent.title()))
93+
.doOnNext(mwQueryLogEvent->Timber.d("Image %s passed filters", mwQueryLogEvent.title() ))
94+
.map(image -> new Contribution(null, null, image.title(),
95+
"", -1, image.date(), image.date(), user,
96+
"", "", STATE_COMPLETED))
97+
.map(contributionDao::toContentValues)
98+
.buffer(10)
99+
.subscribe(imageValues->contentProviderClient.bulkInsert(BASE_URI, imageValues.toArray(EMPTY)));
152100
Timber.d("Oh hai, everyone! Look, a kitty!");
153101
}
154102
}

app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
3131
import fr.free.nrw.commons.mwapi.MediaWikiApi;
3232
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
33+
import fr.free.nrw.commons.mwapi.UserInterface;
3334
import fr.free.nrw.commons.review.ReviewInterface;
3435
import fr.free.nrw.commons.upload.UploadInterface;
3536
import okhttp3.Cache;
@@ -229,4 +230,9 @@ public MediaInterface provideMediaInterface(@Named(NAMED_COMMONS_WIKI_SITE) Wiki
229230
public CategoryInterface provideCategoryInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
230231
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, CategoryInterface.class);
231232
}
233+
@Provides
234+
@Singleton
235+
public UserInterface provideUserInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
236+
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, UserInterface.class);
237+
}
232238
}

app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -83,54 +83,6 @@ public Single<MediaResult> fetchMediaByFilename(String filename) {
8383
});
8484
}
8585

86-
@Override
87-
@NonNull
88-
public LogEventResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException {
89-
CustomMwApi.RequestBuilder builder = api.action("query")
90-
.param("list", "logevents")
91-
.param("letype", "upload")
92-
.param("leprop", "title|timestamp|ids")
93-
.param("leuser", user)
94-
.param("lelimit", limit);
95-
if (!TextUtils.isEmpty(lastModified)) {
96-
builder.param("leend", lastModified);
97-
}
98-
if (!TextUtils.isEmpty(queryContinue)) {
99-
builder.param("lestart", queryContinue);
100-
}
101-
CustomApiResult result = builder.get();
102-
103-
return new LogEventResult(
104-
getLogEventsFromResult(result),
105-
result.getString("/api/query-continue/logevents/@lestart"));
106-
}
107-
108-
@NonNull
109-
private ArrayList<LogEventResult.LogEvent> getLogEventsFromResult(CustomApiResult result) {
110-
ArrayList<CustomApiResult> uploads = result.getNodes("/api/query/logevents/item");
111-
Timber.d("%d results!", uploads.size());
112-
ArrayList<LogEventResult.LogEvent> logEvents = new ArrayList<>();
113-
for (CustomApiResult image : uploads) {
114-
logEvents.add(new LogEventResult.LogEvent(
115-
image.getString("@pageid"),
116-
image.getString("@title"),
117-
parseMWDate(image.getString("@timestamp")))
118-
);
119-
}
120-
return logEvents;
121-
}
122-
123-
@Override
124-
@Nullable
125-
public String revisionsByFilename(String filename) throws IOException {
126-
return api.action("query")
127-
.param("prop", "revisions")
128-
.param("rvprop", "timestamp|content")
129-
.param("titles", filename)
130-
.get()
131-
.getString("/api/query/pages/page/revisions/rev");
132-
}
133-
13486
/**
13587
* Checks to see if a user is currently blocked from Commons
13688
*

app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@ public interface MediaWikiApi {
1414
@NonNull
1515
Single<MediaResult> fetchMediaByFilename(String filename);
1616

17-
@Nullable
18-
String revisionsByFilename(String filename) throws IOException;
19-
20-
@NonNull
21-
LogEventResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException;
22-
2317
boolean isUserBlockedFromCommons();
2418

2519
void logout();
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package fr.free.nrw.commons.mwapi;
2+
3+
import org.wikipedia.dataclient.mwapi.MwQueryLogEvent;
4+
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
5+
import org.wikipedia.dataclient.mwapi.MwQueryResult;
6+
7+
import java.util.Collections;
8+
9+
import javax.inject.Inject;
10+
11+
import io.reactivex.Observable;
12+
13+
public class UserClient {
14+
private final UserInterface userInterface;
15+
16+
@Inject
17+
public UserClient(UserInterface userInterface) {
18+
this.userInterface = userInterface;
19+
}
20+
21+
public Observable<MwQueryLogEvent> logEvents(String user) {
22+
try {
23+
return userInterface.getUserLogEvents(user, Collections.emptyMap())
24+
.map(MwQueryResponse::query)
25+
.map(MwQueryResult::logevents)
26+
.flatMap(Observable::fromIterable);
27+
} catch (Throwable throwable) {
28+
return Observable.empty();
29+
}
30+
31+
}
32+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package fr.free.nrw.commons.mwapi;
2+
3+
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
4+
5+
import java.util.Map;
6+
7+
import io.reactivex.Observable;
8+
import retrofit2.http.GET;
9+
import retrofit2.http.Query;
10+
import retrofit2.http.QueryMap;
11+
12+
import static org.wikipedia.dataclient.Service.MW_API_PREFIX;
13+
14+
public interface UserInterface {
15+
@GET(MW_API_PREFIX+"action=query&list=logevents&letype=upload&leprop=title|timestamp|ids&lelimit=500")
16+
Observable<MwQueryResponse> getUserLogEvents(@Query("leuser") String user, @QueryMap Map<String, String> continuation);
17+
}

0 commit comments

Comments
 (0)