Skip to content

Commit 5d4d91a

Browse files
namedgraphclaude
andcommitted
OntologyFilter: materialize each ontology once under a lock
loadOntology is a compound load + imports-closure + RDFS inference + put, not atomic. Concurrent cold requests for the same ontology could both materialize it (duplicating SPARQL + inference) and race each other's writes. Double-check isCached under the repository lock so a single thread materializes and the others reuse the result. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6b5315f commit 5d4d91a

1 file changed

Lines changed: 10 additions & 2 deletions

File tree

src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,16 @@ public OntModel getOntology(Application app, String uri)
146146
final PrefixGraphRepository repository = app.canAs(EndUserApplication.class) ?
147147
getSystem().getRepository(app.as(EndUserApplication.class)) : getSystem().getRepository();
148148

149-
// only build the materialized model if the ontology is not already cached
150-
if (!repository.isCached(uri)) loadOntology(repository, uri);
149+
// only build the materialized model if the ontology is not already cached; the double check under the
150+
// repository lock ensures a single thread materializes it (loadOntology is a compound load + inference +
151+
// put, not atomic), so concurrent cold requests don't duplicate the work or race each other's writes
152+
if (!repository.isCached(uri))
153+
{
154+
synchronized (repository)
155+
{
156+
if (!repository.isCached(uri)) loadOntology(repository, uri);
157+
}
158+
}
151159

152160
return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL2_FULL_MEM);
153161
}

0 commit comments

Comments
 (0)