Skip to content
Open
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
30 changes: 25 additions & 5 deletions openviking/server/routers/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,17 +229,37 @@ async def _do_reindex(
regenerate: bool,
ctx: RequestContext,
) -> dict:
"""Execute reindex within a lock scope."""
from openviking.storage.transaction import LockContext, get_lock_manager
"""Execute reindex within a lock scope.

Uses a 30-second timeout to allow stale locks (from crashed semantic
processing) to be detected and cleaned up, or for active locks to be
released naturally. Without a timeout, reindex fails immediately when
a lifecycle lock from semantic processing is present, even if that lock
is stale or about to be released.
"""
from openviking.storage.errors import LockAcquisitionError
from openviking.storage.transaction import get_lock_manager

viking_fs = service.viking_fs
path = viking_fs._uri_to_path(uri, ctx=ctx)
lock_manager = get_lock_manager()

# Create a handle with explicit timeout for lock acquisition
handle = lock_manager.create_handle()
try:
# Acquire lock with 30s timeout (allows stale lock cleanup)
acquired = await lock_manager.acquire_point(handle, path, timeout=30.0)
if not acquired:
raise LockAcquisitionError(f"Failed to acquire lock for {uri} after 30s")

async with LockContext(get_lock_manager(), [path], lock_mode="point"):
if regenerate:
return await service.resources.summarize([uri], ctx=ctx)
result = await service.resources.summarize([uri], ctx=ctx)
else:
return await service.resources.build_index([uri], ctx=ctx)
result = await service.resources.build_index([uri], ctx=ctx)

return result
finally:
await lock_manager.release(handle)


async def _background_reindex_tracked(
Expand Down
Loading