Mark Yes a QueryExecution should always be closed when it is done with whether the execution returned results or not because it may be holding connections to the server under the hood.
Note that query results are streamed wherever possible so using a ResultSet after the associated QueryExecution has been closed is likely to fail which would match the behaviour you describe. You can use ResultSetFactory.makeRewindable() to take a full in-memory copy of the results which can be safely used after the QueryExecution is closed. Rob On 29/05/2014 14:33, "Mark Feblowitz" <[email protected]> wrote: >Thanks, Andy - > >I suspected as much. > >I assume that, within each retry loop, I should instantiate the >QueryExecution object and execute the query. Must I also, within that >loop, close the query execution for “unsuccessful” queries? And, for the >successful query, must I perform all of the results processing within >that context? I’ve been bitten more than a couple of times by attempting >to process results outside of the local context of the query execution >and having that fail. > >Thanks, >Mark > > >On May 29, 2014, at 8:54 AM, Andy Seaborne <[email protected]> wrote: > >> Hi Mark, >> >> On 29/05/14 01:21, Mark Feblowitz wrote: >>> I’m encountering a situation in which the assertions (updates) are >>> being posted into TDB via Fuseki at a fairly high rate and queries >>> are also happening pretty quickly. There are times where a query >>> returns an empty result when a known result will eventually land in >>> the triplestore. >>> >>> The current situation is pretty bad - I’m seeing 280 queries and only >>> 35 successful responses. >>> >>> So, I have a couple of issues to resolve, but for the moment I’m >>> trying to focus on retries of a query. Is there a best practice for >>> this? Examples? >>> >>> The query is being executed via a standard QueryFactory >>> >>> com.hp.hpl.jena.query.Query query = QueryFactory.create(queryString) ; >>> QueryExecution qexec = QueryExecutionFactory.sparqlService(service, >>>query); >>> ResultSet results=null; >>> try { >>> results = qexec.execSelect() ; >>> … >>> >>> Immediately following the query I test for results >>> >>> try { >>> results = qexec.execSelect() ; >>> if (!results.hasNext()) { >>> >>> >>> Immediately following the query I test for results >>> >>> try { >> > results = qexec.execSelect() ; >> > if (!results.hasNext()) { >>> >>> and if none are found, I wait a bit and try again - in increasing >>> intervals until successful or until my time limit is exceeded. >>> >>> The question is, must I create a new Query instance and/or a new >>> QueryExecution instance for each retry? And can I reuse the same >>> result set variable for subsequent attempts? >> >> "No" to "Query" , "yes" to QueryExecution. >> >> A Query is the parsed representation and can be used many times in many >>places. >> >> QueryExecution are one-time-use. (shh - it may not matter current in >>some uses but that's what the overall contract is.) >> >>> As for the larger problem, I’m wondering whether independently >>> executed queries (via possibly concurrent, separate invocations of a >>> standalone jar) are handled well by fuseki TDB. My loose >>> understanding is the store is locked for each update. Are the queries >>> queued up, or are they executed with any concurrency? Would there be >>> a better way (other than via Fuseki) for such concurrent queries (SDB >>> is not an option). >> >> Each update for Fuseki+TDB is a transaction. There can be truly >>concurrent readers; other writers are serialized by a lock. >> >> If you ask the query before some write transaction completes, the >>query/reader sees the old state of the database. Transaction are >>isolation level "serialized" and there are no dirty reads etc. >> >> In the case of a remote service query, the HTTP event happens in >>execSelect. That defines the timepoint -- any manipulation of the >>results is relative that that transaction point. >> >> There is no point in looping on >> >> try { >> results = qexec.execSelect() ; >> if (!results.hasNext()) { >> >> once it's hasNext = false, it remains false. You need to redo the >>QueryExecution step. >> >> >> Andy >> >>> >>> Thanks, >>> >>> Mark >>> >>> >>> >>> >>> >>> >> >
