public SearchResponse create(final SearchRequest searchRequest,
                                 final Map<String, ResultCreator> resultCreatorMap) {
        final boolean didSearchComplete;

        if (!store.isComplete()) {
            LOGGER.debug(() -> "Store not complete so will wait for completion or timeout");
            try {
                final Duration effectiveTimeout = getEffectiveTimeout(searchRequest);

                // Block and wait for the store to notify us of its completion/termination, or if the wait is too long
                // we will time out
                LOGGER.debug(() -> "Waiting: effectiveTimeout=" + effectiveTimeout);
                didSearchComplete = store.awaitCompletion(effectiveTimeout.toMillis(), TimeUnit.MILLISECONDS);
                LOGGER.debug(() -> "Finished waiting: effectiveTimeout=" +
                                   effectiveTimeout +
                                   ", didSearchComplete=" +
                                   didSearchComplete);

                if (!didSearchComplete && !searchRequest.incremental()) {
                    // Search didn't complete non-incremental search in time so return a timed out error response
                    return createErrorResponse(
                            searchRequest.getKey(),
                            store,
                            new RuntimeException(SearchResponse.TIMEOUT_MESSAGE + effectiveTimeout));
                }

            } catch (InterruptedException e) {
                LOGGER.trace(e::getMessage, e);
                // Keep interrupting this thread.
                Thread.currentThread().interrupt();

                return createErrorResponse(
                        searchRequest.getKey(),
                        store,
                        new RuntimeException("Thread was interrupted before the search could complete"));
            }
        }

        // We will only get here if the search is complete, or it is an incremental search in which case we don't care
        // about completion state. Therefore, assemble whatever results we currently have
        try {
            // Get completion state before we get results.
            final boolean complete = store.isComplete();

            final List<Result> res = LOGGER.logDurationIfTraceEnabled(() ->
                    getResults(searchRequest, resultCreatorMap), "Getting results");
            LOGGER.debug(() -> "Returning new SearchResponse with results: " +
                               (res.isEmpty()
                                       ? "null"
                                       : res.size()) +
                               ", complete: " +
                               complete +
                               ", isComplete: " +
                               store.isComplete());

            List<Result> results = res;

            if (results.isEmpty()) {
                results = null;
            }

            final List<String> errors = buildCompoundErrorList(store, results);

            final SearchResponse searchResponse = new SearchResponse(
                    searchRequest.getKey(),
                    store.getHighlights(),
                    results,
                    errors,
                    complete);

            if (complete) {
                SearchDebugUtil.writeRequest(searchRequest, false);
                SearchDebugUtil.writeResponse(searchResponse, false);
            }

            return searchResponse;

        } catch (final RuntimeException e) {
            LOGGER.error(() -> "Error getting search results for query " + searchRequest.getKey().toString(), e);

            return createErrorResponse(
                    searchRequest.getKey(),
                    store,
                    new RuntimeException("Error getting search results: [" +
                                         e.getMessage() +
                                         "], see service's logs for details", e));
        }
    }
Build a {@link SearchResponse} from the passed {@link SearchRequest}.

@param searchRequest The {@link SearchRequest} containing the query terms and the result requests
@return A {@link SearchResponse} object that may be one of:
<ul>
<li>A 'complete' {@link SearchResponse} containing all the data requested</li>
<li>An incomplete {@link SearchResponse} containing none, some or all of the data requested, i.e the
currently know results at the point the request is made.</li>
<li>An empty response with an error message indicating the request timed out waiting for a 'complete'
result set. This only applies to non-incremental queries.</li>
<li>An empty response with a different error message. This will happen when some unexpected error has
occurred while assembling the {@link SearchResponse}</li>
</ul>
stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/SearchResponseCreator.java