Skip to content

Commit c8fd8f8

Browse files
committed
Cover an index with no read pointer, and stop sending operators to repair one
A missing read alias is a state advance_read_pointer handles on purpose: an index serving no reads is not already current, so a completed pass publishes it. test_update_read_pointer was what covered that, and it went with the task, so give SearchMigrationFixture a way to drop the alias and pin the behaviour where the rest of the pointer logic is tested. The startup message for a read pointer behind the write pointer sent operators to repair the index by hand. That was right when nothing advanced the pointer on its own; now the first reindex to complete a full pass publishes it, so say that instead.
1 parent 7e1da17 commit c8fd8f8

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

src/palace/manager/scripts/initialization.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ def initialize_search(self) -> None:
154154
self.migrate_search(service, revision)
155155
elif read_pointer.version < revision.version:
156156
self.log.info(
157-
f"Search read pointer is out-of-date (v{read_pointer.version}). Latest is v{revision.version}."
158-
f"This likely means that the reindexing task is in progress. If there is no reindexing task "
159-
f"running, you may need to repair the search index."
157+
f"Search read pointer is out-of-date (v{read_pointer.version}). Latest is v{revision.version}. "
158+
f"This likely means that the reindexing task is in progress. The first run to complete a "
159+
f"full pass over the new index will publish it for reads."
160160
)
161161
elif (
162162
read_pointer.version > revision.version

tests/manager/celery/tasks/test_search.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,22 @@ def __init__(
363363
self.service, self.new_revision
364364
)
365365

366+
def remove_read_pointer(self) -> None:
367+
"""Leave the index with no read pointer at all, serving no reads."""
368+
self.client.indices.update_aliases(
369+
body={
370+
"actions": [
371+
{
372+
"remove": {
373+
"index": "*",
374+
"alias": self.service.read_pointer_name(),
375+
}
376+
}
377+
]
378+
}
379+
)
380+
assert self.service.read_pointer() is None
381+
366382
def assert_pointers(self, read: str, write: str) -> None:
367383
read_pointer = self.service.read_pointer()
368384
write_pointer = self.service.write_pointer()
@@ -404,6 +420,22 @@ def test_search_reindex_advances_read_pointer(
404420
end_to_end_search_fixture.expect_results(fixture.works, "", ordered=False)
405421

406422

423+
def test_search_reindex_advances_read_pointer_when_there_is_none(
424+
celery_fixture: CeleryFixture,
425+
redis_fixture: RedisFixture,
426+
search_migration_fixture: SearchMigrationFixture,
427+
):
428+
fixture = search_migration_fixture
429+
430+
# An index serving no reads at all is not "already current", so a completed pass
431+
# publishes it rather than leaving search with nothing to read from.
432+
fixture.remove_read_pointer()
433+
434+
search_reindex.delay().wait()
435+
436+
fixture.assert_pointers(read=fixture.new_index, write=fixture.new_index)
437+
438+
407439
@patch("palace.manager.celery.tasks.search.random.uniform")
408440
@patch("palace.manager.celery.tasks.search.exponential_backoff")
409441
def test_search_reindex_advances_read_pointer_after_a_retried_batch(

0 commit comments

Comments
 (0)