Gracefully handle exceptions from profile (#65)

pull/66/head
Michael Barry 2022-02-04 06:26:26 -05:00 zatwierdzone przez GitHub
rodzic 8d90470d55
commit e092586dfc
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 70 dodań i 21 usunięć

Wyświetl plik

@ -14,6 +14,8 @@ import java.io.Closeable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import org.locationtech.jts.geom.Envelope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base class for utilities that read {@link SourceFeature SourceFeatures} from a simple data source where geometries
@ -25,6 +27,8 @@ import org.locationtech.jts.geom.Envelope;
*/
public abstract class SimpleReader implements Closeable {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleReader.class);
protected final Stats stats;
protected final String sourceName;
private final Profile profile;
@ -60,9 +64,13 @@ public abstract class SimpleReader implements Closeable {
featuresRead.incrementAndGet();
FeatureCollector features = featureCollectors.get(sourceFeature);
if (sourceFeature.latLonGeometry().getEnvelopeInternal().intersects(latLonBounds)) {
profile.processFeature(sourceFeature, features);
for (FeatureCollector.Feature renderable : features) {
renderer.accept(renderable);
try {
profile.processFeature(sourceFeature, features);
for (FeatureCollector.Feature renderable : features) {
renderer.accept(renderable);
}
} catch (Exception e) {
LOGGER.error("Error processing " + sourceFeature, e);
}
}
}

Wyświetl plik

@ -160,29 +160,41 @@ public class OsmReader implements Closeable, MemoryEstimator.HasEstimate {
}
if (readerElement instanceof ReaderNode node) {
PASS1_NODES.inc();
profile.preprocessOsmNode(OsmElement.fromGraphopper(node));
try {
profile.preprocessOsmNode(OsmElement.fromGraphopper(node));
} catch (Exception e) {
LOGGER.error("Error preprocessing OSM node " + node.getId(), e);
}
// TODO allow limiting node storage to only ones that profile cares about
nodeLocationDb.put(node.getId(), GeoUtils.encodeFlatLocation(node.getLon(), node.getLat()));
} else if (readerElement instanceof ReaderWay way) {
PASS1_WAYS.inc();
profile.preprocessOsmWay(OsmElement.fromGraphopper(way));
try {
profile.preprocessOsmWay(OsmElement.fromGraphopper(way));
} catch (Exception e) {
LOGGER.error("Error preprocessing OSM way " + way.getId(), e);
}
} else if (readerElement instanceof ReaderRelation rel) {
PASS1_RELATIONS.inc();
// don't leak graphhopper classes out through public API
OsmElement.Relation osmRelation = OsmElement.fromGraphopper(rel);
List<OsmRelationInfo> infos = profile.preprocessOsmRelation(osmRelation);
if (infos != null) {
for (OsmRelationInfo info : infos) {
relationInfo.put(rel.getId(), info);
relationInfoSizes.addAndGet(info.estimateMemoryUsageBytes());
for (ReaderRelation.Member member : rel.getMembers()) {
int type = member.getType();
// TODO handle nodes in relations and super-relations
if (type == ReaderRelation.Member.WAY) {
wayToRelations.put(member.getRef(), encodeRelationMembership(member.getRole(), rel.getId()));
try {
List<OsmRelationInfo> infos = profile.preprocessOsmRelation(osmRelation);
if (infos != null) {
for (OsmRelationInfo info : infos) {
relationInfo.put(rel.getId(), info);
relationInfoSizes.addAndGet(info.estimateMemoryUsageBytes());
for (ReaderRelation.Member member : rel.getMembers()) {
int type = member.getType();
// TODO handle nodes in relations and super-relations
if (type == ReaderRelation.Member.WAY) {
wayToRelations.put(member.getRef(), encodeRelationMembership(member.getRole(), rel.getId()));
}
}
}
}
} catch (Exception e) {
LOGGER.error("Error preprocessing OSM relation " + rel.getId(), e);
}
// TODO allow limiting multipolygon storage to only ones that profile cares about
if (isMultipolygon(rel)) {
@ -263,9 +275,19 @@ public class OsmReader implements Closeable, MemoryEstimator.HasEstimate {
// write them intermediate storage
if (feature != null) {
FeatureCollector features = featureCollectors.get(feature);
profile.processFeature(feature, features);
for (FeatureCollector.Feature renderable : features) {
renderer.accept(renderable);
try {
profile.processFeature(feature, features);
for (FeatureCollector.Feature renderable : features) {
renderer.accept(renderable);
}
} catch (Exception e) {
String type = switch (readerElement.getType()) {
case ReaderElement.NODE -> "node";
case ReaderElement.WAY -> "way";
case ReaderElement.RELATION -> "relation";
default -> "element";
};
LOGGER.error("Error processing OSM " + type + " " + readerElement.getId(), e);
}
}
}
@ -292,9 +314,13 @@ public class OsmReader implements Closeable, MemoryEstimator.HasEstimate {
pipeline.awaitAndLog(logger, config.logInterval());
profile.finish(name,
new FeatureCollector.Factory(config, stats),
createFeatureRenderer(writer, config, writer));
try {
profile.finish(name,
new FeatureCollector.Factory(config, stats),
createFeatureRenderer(writer, config, writer));
} catch (Exception e) {
LOGGER.error("Error calling profile.finish", e);
}
timer.stop();
}

Wyświetl plik

@ -1607,4 +1607,19 @@ public class PlanetilerTests {
assertEquals(2146, features, "num buildings");
}
}
@Test
public void testHandleProfileException() throws Exception {
var results = runWithOsmElements(
Map.of("threads", "1"),
List.of(
with(new ReaderNode(1, 0, 0), t -> t.setTag("attr", "value"))
),
(in, features) -> {
throw new IllegalStateException("intentional exception!");
}
);
assertSubmap(Map.of(), results.tiles);
}
}