from django.contrib import admin
-from whoosh.writing import AsyncWriter
 
-from . import index
 from .models import Correspondent, Document, DocumentType, Tag, \
     SavedView, SavedViewFilterRule
 
     created_.short_description = "Created"
 
     def delete_queryset(self, request, queryset):
-        ix = index.open_index()
-        with AsyncWriter(ix) as writer:
+        from documents import index
+
+        with index.open_index_writer() as writer:
             for o in queryset:
                 index.remove_document(writer, o)
+
         super(DocumentAdmin, self).delete_queryset(request, queryset)
 
     def delete_model(self, request, obj):
+        from documents import index
         index.remove_document_from_index(obj)
         super(DocumentAdmin, self).delete_model(request, obj)
 
     def save_model(self, request, obj, form, change):
+        from documents import index
         index.add_or_update_document(obj)
         super(DocumentAdmin, self).save_model(request, obj, form, change)
 
 
 
 from django.db.models import Q
 from django_q.tasks import async_task
-from whoosh.writing import AsyncWriter
 
-from documents import index
 from documents.models import Document, Correspondent, DocumentType
 
 
 def delete(doc_ids):
     Document.objects.filter(id__in=doc_ids).delete()
 
-    ix = index.open_index()
-    with AsyncWriter(ix) as writer:
+    from documents import index
+
+    with index.open_index_writer() as writer:
         for id in doc_ids:
             index.remove_document_by_id(writer, id)
 
 
     return create_in(settings.INDEX_DIR, get_schema())
 
 
+@contextmanager
+def open_index_writer(ix=None, optimize=False):
+    if ix:
+        writer = AsyncWriter(ix)
+    else:
+        writer = AsyncWriter(open_index())
+
+    try:
+        yield writer
+    except Exception as e:
+        logger.exception(str(e))
+        writer.cancel()
+    finally:
+        writer.commit(optimize=optimize)
+
+
 def update_document(writer, doc):
     tags = ",".join([t.name for t in doc.tags.all()])
     writer.update_document(
 
 
 def add_or_update_document(document):
-    ix = open_index()
-    with AsyncWriter(ix) as writer:
+    with open_index_writer() as writer:
         update_document(writer, document)
 
 
 def remove_document_from_index(document):
-    ix = open_index()
-    with AsyncWriter(ix) as writer:
+    with open_index_writer() as writer:
         remove_document(writer, document)
 
 
 
 from django.utils import timezone
 from filelock import FileLock
 
-from .. import index, matching
+from .. import matching
 from ..file_handling import delete_empty_directories, \
     create_source_path_directory, \
     generate_unique_filename
 
 
 def add_to_index(sender, document, **kwargs):
+    from documents import index
+
     index.add_or_update_document(document)
 
 from django.test import TestCase
 from django.utils import timezone
 
+from documents import index
 from documents.admin import DocumentAdmin
 from documents.models import Document
 from documents.tests.utils import DirectoriesMixin
 
 class TestDocumentAdmin(DirectoriesMixin, TestCase):
 
+    def get_document_from_index(self, doc):
+        ix = index.open_index()
+        with ix.searcher() as searcher:
+            return searcher.document(id=doc.id)
+
     def setUp(self) -> None:
         super(TestDocumentAdmin, self).setUp()
         self.doc_admin = DocumentAdmin(model=Document, admin_site=AdminSite())
 
-    @mock.patch("documents.admin.index.add_or_update_document")
-    def test_save_model(self, m):
+    def test_save_model(self):
         doc = Document.objects.create(title="test")
+
         doc.title = "new title"
         self.doc_admin.save_model(None, doc, None, None)
         self.assertEqual(Document.objects.get(id=doc.id).title, "new title")
-        m.assert_called_once()
+        self.assertEqual(self.get_document_from_index(doc)['title'], "new title")
 
-    @mock.patch("documents.admin.index.remove_document")
-    def test_delete_model(self, m):
+    def test_delete_model(self):
         doc = Document.objects.create(title="test")
+        index.add_or_update_document(doc)
+        self.assertIsNotNone(self.get_document_from_index(doc))
+
         self.doc_admin.delete_model(None, doc)
+
         self.assertRaises(Document.DoesNotExist, Document.objects.get, id=doc.id)
-        m.assert_called_once()
+        self.assertIsNone(self.get_document_from_index(doc))
 
-    @mock.patch("documents.admin.index.remove_document")
-    def test_delete_queryset(self, m):
+    def test_delete_queryset(self):
+        docs = []
         for i in range(42):
-            Document.objects.create(title="Many documents with the same title", checksum=f"{i:02}")
+            doc = Document.objects.create(title="Many documents with the same title", checksum=f"{i:02}")
+            docs.append(doc)
+            index.add_or_update_document(doc)
 
         self.assertEqual(Document.objects.count(), 42)
 
+        for doc in docs:
+            self.assertIsNotNone(self.get_document_from_index(doc))
+
         self.doc_admin.delete_queryset(None, Document.objects.all())
 
-        self.assertEqual(m.call_count, 42)
         self.assertEqual(Document.objects.count(), 0)
 
+        for doc in docs:
+            self.assertIsNone(self.get_document_from_index(doc))
+
     def test_created(self):
         doc = Document.objects.create(title="test", created=timezone.datetime(2020, 4, 12))
         self.assertEqual(self.doc_admin.created_(doc), "2020-04-12")
 
     ViewSet
 )
 
-import documents.index as index
 from paperless.db import GnuPG
 from paperless.views import StandardPagination
 from .classifier import load_classifier
     def update(self, request, *args, **kwargs):
         response = super(DocumentViewSet, self).update(
             request, *args, **kwargs)
+        from documents import index
         index.add_or_update_document(self.get_object())
         return response
 
     def destroy(self, request, *args, **kwargs):
+        from documents import index
         index.remove_document_from_index(self.get_object())
         return super(DocumentViewSet, self).destroy(request, *args, **kwargs)
 
 
     permission_classes = (IsAuthenticated,)
 
-    def __init__(self, *args, **kwargs):
-        super(SearchView, self).__init__(*args, **kwargs)
-        self.ix = index.open_index()
-
     def add_infos_to_hit(self, r):
         try:
             doc = Document.objects.get(id=r['id'])
                 }
 
     def get(self, request, format=None):
+        from documents import index
 
         if 'query' in request.query_params:
             query = request.query_params['query']
         if page < 1:
             page = 1
 
+        ix = index.open_index()
+
         try:
-            with index.query_page(self.ix, page, query, more_like_id, more_like_content) as (result_page, corrected_query):  # NOQA: E501
+            with index.query_page(ix, page, query, more_like_id, more_like_content) as (result_page, corrected_query):  # NOQA: E501
                 return Response(
                     {'count': len(result_page),
                      'page': result_page.pagenum,
 
     permission_classes = (IsAuthenticated,)
 
-    def __init__(self, *args, **kwargs):
-        super(SearchAutoCompleteView, self).__init__(*args, **kwargs)
-        self.ix = index.open_index()
-
     def get(self, request, format=None):
         if 'term' in request.query_params:
             term = request.query_params['term']
         else:
             limit = 10
 
-        return Response(index.autocomplete(self.ix, term, limit))
+        from documents import index
+
+        ix = index.open_index()
+
+        return Response(index.autocomplete(ix, term, limit))
 
 
 class StatisticsView(APIView):