fix: bugs
This commit is contained in:
@@ -27,7 +27,6 @@ from fastapi import (
|
||||
)
|
||||
from loguru import logger
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.dependencies import (
|
||||
@@ -591,6 +590,7 @@ async def create_workspace_directory(
|
||||
child_path = f"{parent}/{name}" if parent else name
|
||||
relative_path = user_relative_path(context, child_path)
|
||||
scoped_prefix = user_relative_path(context)
|
||||
path_hash = hashlib.sha256(relative_path.encode("utf-8")).digest()
|
||||
# Validate parent exists: there must be at least one StorageObject whose
|
||||
# relative_path is exactly the parent directory (the directory row itself)
|
||||
# OR lives somewhere below the parent (any file/dir nested under it).
|
||||
@@ -609,42 +609,53 @@ async def create_workspace_directory(
|
||||
status.HTTP_404_NOT_FOUND,
|
||||
"parent directory not found",
|
||||
)
|
||||
# S3 has no real directory objects — the prefix is implicitly
|
||||
# created when a file is uploaded. Conflict detection is best-effort.
|
||||
# Conflict check uses the unique index on (workspace_id, storage_backend, path_hash).
|
||||
# A soft-deleted row at the same path can be revived; an available row is a conflict.
|
||||
existing = await session.scalar(
|
||||
select(StorageObjects.storage_object_id).where(
|
||||
select(StorageObjects)
|
||||
.where(
|
||||
StorageObjects.workspace_id == context.workspace.workspace_id,
|
||||
StorageObjects.relative_path == relative_path,
|
||||
StorageObjects.object_status == "available",
|
||||
StorageObjects.storage_backend == "rustfs",
|
||||
StorageObjects.path_hash == path_hash,
|
||||
)
|
||||
.with_for_update()
|
||||
)
|
||||
if existing is not None:
|
||||
if existing is not None and existing.object_status == "available":
|
||||
raise HTTPException(
|
||||
status.HTTP_409_CONFLICT,
|
||||
"a file or directory with the same path already exists",
|
||||
)
|
||||
directory = StorageObjects(
|
||||
storage_object_id=new_ulid(),
|
||||
workspace_id=context.workspace.workspace_id,
|
||||
object_type="directory",
|
||||
usage_type="working_copy",
|
||||
storage_backend="rustfs",
|
||||
storage_uri=f"inline://directory/{relative_path}",
|
||||
relative_path=relative_path,
|
||||
path_hash=hashlib.sha256(relative_path.encode("utf-8")).digest(),
|
||||
object_status="available",
|
||||
size_bytes=0,
|
||||
visibility="private",
|
||||
created_by=context.user.user_id,
|
||||
)
|
||||
session.add(directory)
|
||||
try:
|
||||
await session.flush()
|
||||
except IntegrityError as exc:
|
||||
raise HTTPException(
|
||||
status.HTTP_409_CONFLICT,
|
||||
"directory already exists",
|
||||
) from exc
|
||||
|
||||
if existing is None:
|
||||
directory = StorageObjects(
|
||||
storage_object_id=new_ulid(),
|
||||
workspace_id=context.workspace.workspace_id,
|
||||
storage_backend="rustfs",
|
||||
object_type="directory",
|
||||
usage_type="working_copy",
|
||||
storage_uri=f"inline://directory/{relative_path}",
|
||||
relative_path=relative_path,
|
||||
path_hash=path_hash,
|
||||
object_status="available",
|
||||
size_bytes=0,
|
||||
visibility="private",
|
||||
created_by=context.user.user_id,
|
||||
)
|
||||
session.add(directory)
|
||||
else:
|
||||
# Revive the soft-deleted row, keeping its original storage_object_id.
|
||||
directory = existing
|
||||
directory.object_status = "available"
|
||||
directory.is_deleted = 0
|
||||
directory.deleted_at = None
|
||||
directory.object_type = "directory"
|
||||
directory.usage_type = "working_copy"
|
||||
directory.storage_uri = f"inline://directory/{relative_path}"
|
||||
directory.size_bytes = 0
|
||||
directory.visibility = "private"
|
||||
directory.created_by = context.user.user_id
|
||||
|
||||
await session.flush()
|
||||
return {
|
||||
"request_id": context.request_id,
|
||||
"data": {
|
||||
|
||||
Reference in New Issue
Block a user