Skip to content

Commit f79f69d

Browse files
authored
fix(storage): use exact lock for content writes (#2064)
1 parent 42484bf commit f79f69d

2 files changed

Lines changed: 13 additions & 10 deletions

File tree

openviking/storage/content_write.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,16 @@ async def _write_direct_with_refresh(
179179
) -> Dict[str, Any]:
180180
lock_manager = get_lock_manager()
181181
handle = lock_manager.create_handle()
182-
lock_path = self._viking_fs._uri_to_path(root_uri, ctx=ctx)
183-
acquired = await lock_manager.acquire_tree(handle, lock_path)
182+
lock_path = self._viking_fs._uri_to_path(uri, ctx=ctx)
183+
acquired = await lock_manager.acquire_exact_path(handle, lock_path)
184184
if not acquired:
185185
await lock_manager.release(handle)
186186
raise InvalidArgumentError(f"resource is busy and cannot be written now: {uri}")
187187

188188
previous_content: Optional[str] = None
189189
content_written = False
190-
lock_transferred = False
190+
semantic_enqueued = False
191+
lock_released = False
191192
try:
192193
if mode != "create":
193194
previous_content = await self._viking_fs.read_file(uri, ctx=ctx)
@@ -200,10 +201,12 @@ async def _write_direct_with_refresh(
200201
changed_uri=uri,
201202
context_type=context_type,
202203
ctx=ctx,
203-
lifecycle_lock_handle_id=handle.id,
204+
lifecycle_lock_handle_id="",
204205
change_type="added" if mode == "create" else "modified",
205206
)
206-
lock_transferred = True
207+
semantic_enqueued = True
208+
await lock_manager.release(handle)
209+
lock_released = True
207210
queue_status = (
208211
await self._wait_for_request(telemetry_id=telemetry_id, timeout=timeout)
209212
if wait
@@ -219,15 +222,15 @@ async def _write_direct_with_refresh(
219222
queue_status=queue_status,
220223
)
221224
except Exception:
222-
if not lock_transferred and content_written:
225+
if not semantic_enqueued and content_written:
223226
await self._rollback_direct_write(
224227
uri=uri,
225228
previous_content=previous_content,
226229
mode=mode,
227230
ctx=ctx,
228231
lock_handle=handle,
229232
)
230-
if not lock_transferred:
233+
if not lock_released:
231234
await lock_manager.release(handle)
232235
raise
233236
finally:

tests/server/test_content_write_service.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ async def test_resource_write_semantic_refresh_uses_coalesce_key(monkeypatch):
285285

286286

287287
@pytest.mark.asyncio
288-
async def test_write_timeout_after_enqueue_does_not_release_resource_lock(monkeypatch):
288+
async def test_write_timeout_after_enqueue_releases_resource_lock(monkeypatch):
289289
file_uri = "viking://resources/demo/doc.md"
290290
root_uri = "viking://resources/demo"
291291
ctx = RequestContext(user=UserIdentifier.the_default_user(), role=Role.USER)
@@ -317,7 +317,7 @@ async def _fake_wait_for_request(*, telemetry_id, timeout):
317317
wait=True,
318318
)
319319

320-
assert lock_manager.release_calls == []
320+
assert lock_manager.release_calls == ["lock-1"]
321321
assert viking_fs.delete_temp_calls == []
322322
assert viking_fs.content[file_uri] == "updated"
323323

@@ -358,7 +358,7 @@ async def _fake_enqueue_semantic_refresh(**kwargs):
358358
assert captured_enqueue["changed_uri"] == file_uri
359359
assert captured_enqueue["change_type"] == "modified"
360360
assert viking_fs.delete_temp_calls == []
361-
assert lock_manager.release_calls == []
361+
assert lock_manager.release_calls == ["lock-1"]
362362

363363

364364
@pytest.mark.asyncio

0 commit comments

Comments
 (0)