Skip to content

Commit 4e80c8c

Browse files
authored
Release v1.3.3 (#15)
* Added handling for badly formed URLs * Fixed handling for badly formed URLs * Added debug line to help with triage of issue * Tests failed on Jenkins - trigger rerun * Added announcements of thread start * Reduced thread start output to be included only in the verbose output * Attempting to fix the tests again * Now sleeping for random millisecond time before starting each thread * Reduced thread count * Fixed test - character has moved to moogle * Added output of exceptions from 'does not exist' * Error-code character pages now print status code to exception * Recursively retry when experiencing 429 errors * Fixed spelling errror * Increased retry timeout * Update CHANGELOG.md * Update CHANGELOG.md
1 parent 9e5dc4f commit 4e80c8c

File tree

7 files changed

+59
-13
lines changed

7 files changed

+59
-13
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
v1.3.3
2+
======
3+
* If the Gatherer experiences a HTTP error code `429` (Too many requests), it will pause for 1-20 milliseconds and retry via recursive method call.
4+
15
v1.3.2
26
======
37
* New reputation columns accidentally deleted from CREATE TABLE script.

pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.ffxivcensus.gatherer</groupId>
88
<artifactId>XIVStats-Gatherer-Java</artifactId>
9-
<version>v1.3.2</version>
9+
<version>v1.3.3</version>
1010
<name>XIVStats Lodestone Gatherer</name>
1111
<url>https://github.com/xivstats</url>
1212

@@ -180,6 +180,11 @@
180180
<artifactId>unirest-java</artifactId>
181181
<version>1.4.9</version>
182182
</dependency>
183+
<dependency>
184+
<groupId>commons-lang</groupId>
185+
<artifactId>commons-lang</artifactId>
186+
<version>2.6</version>
187+
</dependency>
183188
</dependencies>
184189

185190
</project>

src/main/java/com/ffxivcensus/gatherer/Gatherer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
public class Gatherer implements Runnable {
1717

18-
GathererController parent;
18+
private GathererController parent;
1919

2020
/**
2121
* Default constructor
@@ -31,6 +31,9 @@ public void run() {
3131
int nextID = parent.getNextID();
3232
while (nextID != -1) { //While we still have IDs to parse
3333
try {
34+
if(parent.isVerbose()) {
35+
System.out.println("Starting evaluation of player ID: " +nextID);
36+
}
3437
//Parse players and write them to DB
3538
String out = parent.writeToDB(Player.getPlayer(nextID));
3639
if (!parent.isQuiet()) { //If not running in quiet mode

src/main/java/com/ffxivcensus/gatherer/GathererController.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import java.sql.DriverManager;
1515
import java.sql.SQLException;
1616
import java.sql.Statement;
17+
import java.util.Random;
18+
import java.util.concurrent.TimeUnit;
1719

1820
/**
1921
* GathererController class of character gathering program. This class makes calls to fetch records from the lodestone, and then
@@ -429,7 +431,20 @@ private void gatherRange() {
429431

430432
//Start up threads
431433
for (Thread thread : threads) {
434+
if(this.isVerbose()) {
435+
System.out.println("Starting thread with id " + thread.getId());
436+
}
432437
thread.start();
438+
try {
439+
//Generate random number 1-10 and sleep for it
440+
Random rand = new Random();
441+
442+
int randomNum = rand.nextInt((10 - 1) + 1) + 1;
443+
444+
TimeUnit.MILLISECONDS.sleep(randomNum);
445+
} catch (InterruptedException e) {
446+
e.printStackTrace();
447+
}
433448
}
434449

435450
//Spin down threads

src/main/java/com/ffxivcensus/gatherer/Player.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
import org.jsoup.select.Elements;
1111

1212
import java.io.IOException;
13+
import java.net.MalformedURLException;
1314
import java.text.DateFormat;
1415
import java.text.ParseException;
1516
import java.text.SimpleDateFormat;
1617
import java.util.ArrayList;
1718
import java.util.Calendar;
1819
import java.util.Date;
20+
import java.util.Random;
21+
import java.util.concurrent.TimeUnit;
1922
import java.util.regex.Pattern;
2023

2124
/**
@@ -1864,14 +1867,14 @@ public static Player getPlayer(int playerID) throws Exception {
18641867

18651868
try {
18661869
//Fetch the specified URL
1867-
doc = Jsoup.connect(url).get();
1870+
doc = Jsoup.connect(url).timeout(5000).get();
18681871
player.setPlayerName(getNameFromPage(doc));
18691872
player.setRealm(getRealmFromPage(doc));
18701873
player.setRace(getRaceFromPage(doc));
18711874
player.setGender(getGenderFromPage(doc));
18721875
player.setGrandCompany(getGrandCompanyFromPage(doc));
18731876
player.setFreeCompany(getFreeCompanyFromPage(doc));
1874-
player.setDateImgLastModified(getDateLastUpdatedFromPage(doc));
1877+
player.setDateImgLastModified(getDateLastUpdatedFromPage(doc,playerID));
18751878
player.setLevels(getLevelsFromPage(doc));
18761879
player.setMounts(getMountsFromPage(doc));
18771880
player.setMinions(getMinionsFromPage(doc));
@@ -1917,7 +1920,19 @@ public static Player getPlayer(int playerID) throws Exception {
19171920
player.setIsLegacyPlayer(player.doesPlayerHaveMount("Legacy Chocobo"));
19181921
player.setActive(player.isPlayerActiveInDateRange());
19191922
} catch (IOException ioEx) {
1920-
throw new Exception("Character " + playerID + " does not exist.");
1923+
String strEx = org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(ioEx);
1924+
String statusCode = strEx.split("\\s+")[5].replace("Status=","").replace(",","");
1925+
if(statusCode.equals("429")) {
1926+
//Generate random number 1-20 and sleep for it
1927+
Random rand = new Random();
1928+
1929+
int randomNum = rand.nextInt((20 - 1) + 1) + 1;
1930+
System.out.println("Experiencing rate limiting (HTTP 429) while fetching id " + playerID + ", waiting " + randomNum + "ms then retrying...");
1931+
TimeUnit.MILLISECONDS.sleep(randomNum);
1932+
player = Player.getPlayer(playerID);
1933+
} else {
1934+
throw new Exception("Character " + playerID + " does not exist. Status: " + statusCode);
1935+
}
19211936
}
19221937
return player;
19231938
}
@@ -2146,7 +2161,7 @@ private static ArrayList getMountsFromPage(Document doc) {
21462161
* @param doc the lodestone profile page to parse
21472162
* @return the date on which the full body image was last modified.
21482163
*/
2149-
private static Date getDateLastUpdatedFromPage(Document doc) throws Exception {
2164+
private static Date getDateLastUpdatedFromPage(Document doc, int id) throws Exception {
21502165
Date dateLastModified = new Date();
21512166
//Get character image URL.
21522167
String imgUrl = doc.getElementsByClass("bg_chara_264").get(0).getElementsByTag("img").get(0).attr("src");
@@ -2156,8 +2171,10 @@ private static Date getDateLastUpdatedFromPage(Document doc) throws Exception {
21562171
HttpResponse<JsonNode> jsonResponse = Unirest.head(imgUrl).asJson();
21572172

21582173
strLastModifiedDate = jsonResponse.getHeaders().get("Last-Modified").toString();
2159-
} catch (UnirestException e) {
2160-
e.printStackTrace();
2174+
}
2175+
catch (Exception e) {
2176+
System.out.println("Setting last-active date to ARR launch date due to an an error loading character " + id + "'s profile image: " + e.getMessage());
2177+
strLastModifiedDate = "[Sat, 24 Aug 2013 00:00:01 GMT]";
21612178
}
21622179

21632180
strLastModifiedDate = strLastModifiedDate.replace("[", "");
@@ -2167,7 +2184,7 @@ private static Date getDateLastUpdatedFromPage(Document doc) throws Exception {
21672184
try {
21682185
dateLastModified = dateFormat.parse(strLastModifiedDate);
21692186
} catch (ParseException e) {
2170-
throw new Exception("Could not correctly parse date 'Last-Modified' header from full body image");
2187+
throw new Exception("Could not correctly parse date 'Last-Modified' header from full body image for character id" + id);
21712188
}
21722189
return dateLastModified;
21732190
}

src/test/java/com/ffxivcensus/gatherer/GathererControllerTest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ public void testRunBasic() throws IOException, SAXException, ParserConfiguration
114114
int endId = 11887010;
115115
GathererController gathererController = new GathererController(startId, endId);
116116
gathererController.setTableName("tblplayers_test_3");
117+
gathererController.setVerbose(true);
118+
gathererController.setThreadLimit(40);
117119
try {
118120
gathererController.run();
119121
} catch (Exception e) {
@@ -207,7 +209,7 @@ public void testRunSplitTables() {
207209
int startId = 1557260;
208210
int endId = 1558260;
209211

210-
GathererController gathererController = new GathererController(startId, endId, false, true, false, false, false, dbHost, dbName, dbUser, dbPassword, 71, "_test", true);
212+
GathererController gathererController = new GathererController(startId, endId, false, true, false, false, false, dbHost, dbName, dbUser, dbPassword, 50, "_test", true);
211213
try {
212214
gathererController.run();
213215
} catch (Exception e) {
@@ -231,12 +233,12 @@ public void testRunSplitTables() {
231233
assertTrue(addedIDsCerberus.contains(1557648));
232234
assertTrue(addedIDsCerberus.contains(1558244));
233235

234-
//Test for ids that will exist on shiva (realm of end char)
235-
assertTrue(addedIDsShiva.contains(endId));
236+
236237
assertTrue(addedIDsShiva.contains(1557297));
237238

238239
//Test for ids that will exist on Moogle
239240
assertTrue(addedIDsMoogle.contains(1557265));
241+
assertTrue(addedIDsMoogle.contains(endId));
240242
assertTrue(addedIDsMoogle.contains(1557301));
241243

242244
//Test that gatherer has not written records that don't exist on cerberus

src/test/java/com/ffxivcensus/gatherer/PlayerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public void testGetPlayer() throws Exception {
163163
* Perform a test of the getPlayer method using character #501646 (Omega Venom, Cerberus) to test data that could
164164
* not be tested with other tests.
165165
*
166-
* @throws Exception exception thrown when reading non-existant character.
166+
* @throws Exception exception thrown when reading non-existent character.
167167
*/
168168
@org.junit.Test
169169
public void testGetVeteranPlayer() throws Exception {

0 commit comments

Comments
 (0)