Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ services:
# concurrent with writes are a suspected corruption trigger upstream
# (rdf4j#5960/#4806), so this is a backstop, not a first-line limit.
- RDF4J_QUERY_TIMEOUT_SECONDS=${RDF4J_QUERY_TIMEOUT_SECONDS:-60}
# Client-side socket timeout (ms) for this app's own reads from rdf4j
# (Utils.getHttpRequestConfig). 10s is aggressive for a store that is slow
# rather than broken: the read raises QueryInterruptedException, the loader's
# generic retry loops treat that as transient, and the retries add load, which
# makes the next read slower still. That storm saturated the OVH node on
# 2026-08-31 and again after the migration. Raise it where rdf4j shares CPU
# with other services; it is a timeout, so a higher value costs nothing when
# reads are fast.
- NANOPUB_QUERY_FETCHING_SOCKET_TIMEOUT=${NANOPUB_QUERY_FETCHING_SOCKET_TIMEOUT:-10000}
# One-shot repair/resync switch: re-streams the whole registry at startup;
# per-repo isLoaded checks skip everything already present, so WITHOUT a
# store wipe this fills holes (missing nanopubs) idempotently. Set it for
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/knowledgepixels/query/TripleStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,16 @@ private void createRepo(String repoName) {
indexTypes = "spoc,posc,ospc";
}

// valueEvictionInterval 0 disables LMDB's value-cache garbage collection.
// Without it, rdf4j frees unused value IDs and REUSES them; a stale reference
// then dereferences to a different value, which is the value-ID-remap
// corruption we hit eight times between 2026-08-20 and 2026-08-31 (upstream
// eclipse-rdf4j/rdf4j#5970). Crucially the eviction pass "is also run after
// opening the database" (ValueStore.java), which explains why every one of
// those events followed a restart of the affected store. Disabling it is the
// workaround recommended upstream on 2026-08-31; it costs disk (dead values
// are never reclaimed) but not memory — gcIds() returns early, so nothing
// accumulates on the heap. Revisit once the upstream race is fixed.
String createRegularRepoQueryString =
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.\n" +
"@prefix rep: <http://www.openrdf.org/config/repository#>.\n" +
Expand All @@ -441,6 +451,7 @@ private void createRepo(String repoName) {
" sail:sailType \"rdf4j:LmdbStore\" ;\n" +
" sail:iterationCacheSyncThreshold \"10000\";\n" +
" lmdb:tripleIndexes \"" + indexTypes + "\" ;\n" +
" lmdb:valueEvictionInterval 0 ;\n" +
" sb:defaultQueryEvaluationMode \"STANDARD\"\n" +
" ]\n"
+ " ].\n";
Expand Down Expand Up @@ -468,6 +479,7 @@ private void createRepo(String repoName) {
" sail:sailType \"rdf4j:LmdbStore\" ;\n" +
" sail:iterationCacheSyncThreshold \"10000\";\n" +
" lmdb:tripleIndexes \"" + indexTypes + "\" ;\n" +
" lmdb:valueEvictionInterval 0 ;\n" +
" sb:defaultQueryEvaluationMode \"STANDARD\"\n" +
" ]\n" +
" ]\n" +
Expand Down