Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions solrorbit/worker_coordinator/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -1151,18 +1151,18 @@ async def __call__(self, client, params):
for doc in doc_stream:
batch.append(doc)
if len(batch) >= batch_size:
total_docs += len(batch)
try:
await _run_in_executor(sc.add, collection, batch, commit=False, commitWithin=1000)
total_docs += len(batch)
except pysolr.SolrError as exc:
logging.getLogger(__name__).error("Bulk index error on batch: %s", exc)
errors += len(batch)
batch = []

if batch:
total_docs += len(batch)
try:
await _run_in_executor(sc.add, collection, batch, commit=False, commitWithin=1000)
total_docs += len(batch)
except pysolr.SolrError as exc:
logging.getLogger(__name__).error("Bulk index error on final batch: %s", exc)
errors += len(batch)
Expand All @@ -1171,6 +1171,7 @@ async def __call__(self, client, params):
await _run_in_executor(sc.commit, collection)

elapsed = time.perf_counter() - start
# total_docs counts every document sent, so this is the number actually indexed.
weight = total_docs - errors

return {
Expand Down
35 changes: 35 additions & 0 deletions tests/unit/solr/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,41 @@ def test_bulk_index_reports_errors(self):
self.assertFalse(result["success"])
self.assertGreater(result["error-count"], 0)

def test_partial_failure_counts_failed_docs_once(self):
"""A failed batch is reported as errors, not also subtracted from the indexed docs."""
import pysolr
mock_sc = MagicMock()
mock_sc.add.side_effect = [None, pysolr.SolrError("Indexing error")]

lines = [
'{"index": {"_id": "1"}}',
'{"title": "doc"}',
'{"index": {"_id": "2"}}',
'{"title": "doc"}',
]
params = {**self._params(lines), "bulk-size": 1}
result = _run(SolrBulkIndex()(mock_sc, params))

self.assertEqual(1, result["weight"])
self.assertEqual(2, result["bulk-size"])
self.assertEqual(1, result["error-count"])
self.assertFalse(result["success"])

def test_failed_bulk_has_zero_weight(self):
import pysolr
mock_sc = MagicMock()
mock_sc.add.side_effect = pysolr.SolrError("Indexing error")

lines = [
'{"index": {"_id": "1"}}',
'{"title": "doc"}',
]
result = _run(SolrBulkIndex()(mock_sc, self._params(lines)))

self.assertEqual(0, result["weight"])
self.assertEqual(1, result["bulk-size"])
self.assertEqual(1, result["error-count"])

def test_simple_ndjson_format(self):
"""Test simple NDJSON (one doc per line, no action lines)."""
mock_sc = MagicMock()
Expand Down
Loading