fix: script not found

This commit is contained in:
tao.chen
2026-08-04 14:24:55 +08:00
parent 1cf2eecbc9
commit 94a1aef7c7
4 changed files with 37 additions and 49 deletions
+37 -13
View File
@@ -21,6 +21,7 @@ from fastapi import (
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from common.config import settings
from common.db.models import (
Scripts,
StorageObjects,
@@ -356,19 +357,40 @@ async def create_script_record(
detail=exc.detail,
) from exc
# Synthesise a storage_data-shaped dict from the Jupyter response
# so the existing script_payload + response shape keep working.
# The storage_object_id is a fresh ULID — there is no real
# StorageObject row for this file; downstream list/get operations
# that JOIN StorageObjects will skip jupyter-only scripts.
# Build a real StorageObjects row so the file participates in
# workspace-tree / list / get queries that JOIN this table. The
# bytes live in the Jupyter mount; rclone replicates them to
# RustFS asynchronously. We mark the row "available" because the
# file is queryable as a workspace file from the user's POV; the
# storage_uri points at where the replicated bytes will land.
object_id = new_ulid()
storage_data = {
"storage_object_id": object_id,
"relative_path": jupyter_name,
"object_key": f"{workspace_id}/{jupyter_name}",
"content_hash": content_hash,
"size_bytes": size_bytes,
}
object_key = f"{workspace_id}/{jupyter_name}"
bucket_name = settings.rustfs_workspace_bucket
relative_path = user_relative_path(context, jupyter_name)
mime_type = mimetypes.guess_type(jupyter_name)[0]
storage_object = StorageObjects(
storage_object_id=object_id,
workspace_id=context.workspace.workspace_id,
owner_user_id=context.user.user_id,
object_type="file",
usage_type="working_copy",
storage_backend="rustfs",
bucket_name=bucket_name,
object_key=object_key,
object_key_hash=hashlib.sha256(object_key.encode("utf-8")).digest(),
storage_uri=f"s3://{bucket_name}/{object_key}",
file_name=name,
file_extension=PurePosixPath(jupyter_name).suffix.lower() or None,
mime_type=mime_type,
size_bytes=size_bytes,
content_hash=content_hash,
visibility=visibility,
is_immutable=0,
object_status="available",
created_by=context.user.user_id,
relative_path=relative_path,
path_hash=hashlib.sha256(relative_path.encode("utf-8")).digest(),
)
script = Scripts(
script_id=script_id,
workspace_id=context.workspace.workspace_id,
@@ -379,10 +401,12 @@ async def create_script_record(
visibility=visibility,
status="active",
)
session.add(storage_object)
session.add(script)
await session.flush()
await session.refresh(storage_object)
await session.refresh(script)
return script, storage_data
return script, storage_object
@router.post("/api/v1/scripts", status_code=status.HTTP_201_CREATED)
-1
View File
@@ -222,7 +222,6 @@ export function useApi(): WorkspaceBoundApi {
rawApi.createJupyterAccessTicket(workspaceId, session),
getLatestScriptVersion: (scriptId) =>
rawApi.getLatestScriptVersion(workspaceId, scriptId),
listScriptVersions: (scriptId) => rawApi.listScriptVersions(workspaceId, scriptId),
publishScriptVersion: (input) => rawApi.publishScriptVersion(workspaceId, input),
listSchedules: () => rawApi.listSchedules(workspaceId),
getSchedule: (scheduleId) => rawApi.getSchedule(workspaceId, scheduleId),
@@ -162,8 +162,6 @@ function AuthenticatedModelPlatformApp() {
scriptId: string;
message: string;
} | null>(null);
const [versions, setVersions] = useState<StableVersion[]>([]);
const [versionsLoading, setVersionsLoading] = useState(false);
const [latestVersion, setLatestVersion] = useState<LatestVersion | null>(
null,
);
@@ -248,12 +246,10 @@ function AuthenticatedModelPlatformApp() {
useEffect(() => {
if (!selectedId) {
setVersions([]);
setLatestVersion(null);
return;
}
let ignore = false;
setVersionsLoading(true);
setLatestVersionLoading(true);
void api.getLatestScriptVersion(selectedId)
.then((item) => {
@@ -273,21 +269,6 @@ function AuthenticatedModelPlatformApp() {
.finally(() => {
if (!ignore) setLatestVersionLoading(false);
});
void api.listScriptVersions(selectedId)
.then((items) => {
if (!ignore) setVersions(items);
})
.catch((error) => {
if (!ignore) {
setToast({
tone: "error",
message: error instanceof Error ? error.message : "版本列表加载失败",
});
}
})
.finally(() => {
if (!ignore) setVersionsLoading(false);
});
return () => {
ignore = true;
};
@@ -595,10 +576,6 @@ function AuthenticatedModelPlatformApp() {
releaseNote,
visibility: publishVisibility,
});
setVersions((items) => [
version,
...items.filter((item) => item.versions_id !== version.versions_id),
]);
setPublishTarget(null);
setPublishedVersion(version);
setToast({
-12
View File
@@ -574,17 +574,6 @@ export async function getLatestScriptVersion(
);
}
export async function listScriptVersions(
workspaceId: string,
scriptId: string,
): Promise<StableVersion[]> {
return apiRequest<StableVersion[]>(
`/api/v1/scripts/${scriptId}/versions`,
{},
workspaceId,
);
}
export async function publishScriptVersion(
workspaceId: string,
input: {
@@ -1119,7 +1108,6 @@ export type WorkspaceBoundApi = {
session: ActiveEditSession,
) => Promise<JupyterAccessTicket>;
getLatestScriptVersion: (scriptId: string) => Promise<LatestVersion | null>;
listScriptVersions: (scriptId: string) => Promise<StableVersion[]>;
publishScriptVersion: (
input: Parameters<typeof publishScriptVersion>[1],
) => Promise<StableVersion>;