Skip to content

Commit 9f54e28

Browse files
committed
Refactor
1 parent 7ab54d8 commit 9f54e28

1 file changed

Lines changed: 38 additions & 29 deletions

File tree

src/main/java/org/opendcs/usgs/waterdata/UsgsWaterDataApi.java

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -97,55 +97,64 @@ private static List<DailyValue> fetchDailyValues(String timeSeriesId, String sta
9797
}
9898

9999
/**
100-
* Fetches continuous values for a date range, paging in chunks when necessary.
100+
* Fetches continuous values for a date range, paging in chunks when necessary.
101101
*/
102102
private static List<InstantaneousValue> fetchContinuousValues(String timeSeriesId, String startDate, String endDate) throws Exception {
103103
if (TestSite.isTestSeriesId(timeSeriesId))
104104
return TestSite.generateContinuousValues(startDate, endDate);
105105

106-
List<InstantaneousValue> all = new ArrayList<>();
107106
Instant rangeEnd = Instant.parse(normalizeToInstant(endDate));
108107
Instant chunkStart = Instant.parse(normalizeToInstant(startDate));
108+
109+
List<InstantaneousValue> all = new ArrayList<>();
109110
Instant lastSeen = null;
110-
boolean continuation = false;
111111
while (chunkStart.isBefore(rangeEnd)) {
112-
// Cap the request at the API's maximum time envelope.
113112
Instant windowEnd = chunkStart.plus(MAX_WINDOW_DAYS, ChronoUnit.DAYS);
114113
if (windowEnd.isAfter(rangeEnd)) windowEnd = rangeEnd;
115114

116-
String url = String.format(CONTINUOUS_URL_ID, timeSeriesId, chunkStart.toString(), windowEnd.toString());
117-
String csv = WebUtility.getPage(url);
118-
List<InstantaneousValue> page = (csv == null || csv.isBlank())
119-
? Collections.emptyList()
120-
: CsvFile.fromString(csv).mapRows(InstantaneousValue::fromRow);
121-
122-
for (int i = 0; i < page.size(); i++) {
123-
InstantaneousValue iv = page.get(i);
124-
// A continuation query is inclusive of its start, so its first point repeats
125-
// the previous chunk's last point. Drop that one expected boundary duplicate.
126-
if (continuation && i == 0 && iv.time.equals(lastSeen)) continue;
127-
// Any other repeated time-stamp would break a database save. Keep the first
128-
// value for that time, drop the rest, and warn so it can be investigated.
129-
if (lastSeen != null && !iv.time.isAfter(lastSeen)) {
130-
logger.warning("Dropping duplicate time-stamp " + iv.time
131-
+ " in continuous series " + timeSeriesId);
132-
continue;
133-
}
134-
all.add(iv);
135-
lastSeen = iv.time;
136-
}
137-
continuation = true;
115+
List<InstantaneousValue> page = fetchContinuousPage(timeSeriesId, chunkStart, windowEnd);
116+
lastSeen = appendDeduplicated(all, page, lastSeen, timeSeriesId);
138117

139118
if (page.size() >= PAGE_LIMIT && lastSeen != null && lastSeen.isAfter(chunkStart)) {
140-
// Window was truncated at the page limit; resume from its last point.
119+
// Response was truncated at the page limit; resume from its last point.
141120
chunkStart = lastSeen;
142121
logger.info("Continuous query returned a full page; fetching next chunk from " + chunkStart);
143122
} else {
144-
// Window exhausted; advance to the next time window.
145123
chunkStart = windowEnd;
146124
}
147125
}
148-
return all.isEmpty() ? Collections.emptyList() : all;
126+
return all;
127+
}
128+
129+
/**
130+
* Fetches a single page of continuous values for one time window.
131+
*/
132+
private static List<InstantaneousValue> fetchContinuousPage(String timeSeriesId, Instant start, Instant end) throws Exception {
133+
String url = String.format(CONTINUOUS_URL_ID, timeSeriesId, start.toString(), end.toString());
134+
String csv = WebUtility.getPage(url);
135+
if (csv == null || csv.isBlank()) return Collections.emptyList();
136+
return CsvFile.fromString(csv).mapRows(InstantaneousValue::fromRow);
137+
}
138+
139+
/**
140+
* Appends a page's values to dest, skipping potental duplicates at the page boundary.
141+
*/
142+
private static Instant appendDeduplicated(List<InstantaneousValue> dest, List<InstantaneousValue> page,
143+
Instant lastSeen, String timeSeriesId) {
144+
for (int i = 0; i < page.size(); i++) {
145+
InstantaneousValue iv = page.get(i);
146+
if (lastSeen != null && !iv.time.isAfter(lastSeen)) {
147+
boolean expectedBoundaryDuplicate = i == 0 && iv.time.equals(lastSeen);
148+
if (!expectedBoundaryDuplicate) {
149+
logger.warning("Dropping duplicate time-stamp " + iv.time
150+
+ " in continuous series " + timeSeriesId);
151+
}
152+
continue;
153+
}
154+
dest.add(iv);
155+
lastSeen = iv.time;
156+
}
157+
return lastSeen;
149158
}
150159

151160
/**

0 commit comments

Comments
 (0)