private IndexShardWriter openWriter(final long indexShardId) {
        LOGGER.debug(() -> "Opening " + indexShardId);

        return securityContext.asProcessingUserResult(() -> {
            final Optional<IndexShard> optional = indexShardDao.fetch(indexShardId);
            if (optional.isEmpty()) {
                throw new IndexException("Unable to find index shard with id = " + indexShardId);
            }

            // Get the index fields.
            final IndexShard indexShard = optional.get();
            final LuceneIndexDoc luceneIndexDoc = luceneIndexDocCache.get(new DocRef(LuceneIndexDoc.TYPE,
                    indexShard.getIndexUuid()));

            // Mark the index shard as opening.
            final boolean isNew = IndexShardStatus.NEW.equals(indexShard.getStatus());
            try {
                if (!indexShardDao.setStatus(indexShardId, IndexShardStatus.OPENING)) {
                    throw new IndexException("Unable to set index shard status to OPENING");
                }

                final LuceneVersion luceneVersion = LuceneVersionUtil
                        .getLuceneVersion(indexShard.getIndexVersion());
                final LuceneProvider luceneProvider = luceneProviderFactoryProvider.get().get(luceneVersion);
                final IndexShardWriter writer = luceneProvider.createIndexShardWriter(
                        indexShard,
                        luceneIndexDoc.getMaxDocsPerShard());

                // We have opened the index so update the DB object.
                if (indexShardDao.setStatus(indexShardId, IndexShardStatus.OPEN)) {
                    // Output some debug.
                    LOGGER.debug(() ->
                            "Opened " + indexShardId + " in " +
                            (System.currentTimeMillis() - writer.getCreationTime()) + "ms");
                }

                return writer;

            } catch (final RuntimeException e) {
                if (isNew) {
                    try {
                        // If this was a new shard then delete it immediately.
                        LOGGER.error(() -> "Deleting new index shard because (" + e + ")", e);
                        indexShardDao.logicalDelete(indexShardId);
                    } catch (final RuntimeException e2) {
                        LOGGER.error(() -> "Unable to delete new index shard (" + e2.getMessage() + ")", e2);
                    }

                } else {
                    try {
                        // Something went wrong so set the shard state back to closed.
                        LOGGER.error(() -> "Error opening index shard " + indexShardId, e);
                        indexShardDao.reset(indexShardId);
                    } catch (final RuntimeException e2) {
                        LOGGER.error(() -> "Unable to reset index shard (" + e2.getMessage() + ")", e2);
                    }
                }

                throw e;
            }
        });
    }
@param indexShardId The id of the index shard.
@return A writer for the index shard.
stroom-index/stroom-index-impl/src/main/java/stroom/index/impl/IndexShardWriterCacheImpl.java