diff --git a/backend/server/src/index.ts b/backend/server/src/index.ts index 8099bbe..f66553c 100644 --- a/backend/server/src/index.ts +++ b/backend/server/src/index.ts @@ -176,17 +176,20 @@ io.on("connection", async (socket) => { ); }; + // Copy all files from the project to the container const sandboxFiles = await getSandboxFiles(data.sandboxId); + const containerFiles = containers[data.sandboxId].files; const promises = sandboxFiles.fileData.map(async (file) => { - const filePath = path.join(dirName, file.id); try { - await containers[data.sandboxId].files.makeDir( - path.dirname(filePath) - ); + const filePath = path.join(dirName, file.id); + const parentDirectory = path.dirname(filePath); + if (!containerFiles.exists(parentDirectory)) { + await containerFiles.makeDir(parentDirectory); + } + await containerFiles.write(filePath, file.data); } catch (e: any) { - console.log("Failed to create directory: " + e); + console.log("Failed to create file: " + e); } - await containers[data.sandboxId].files.write(filePath, file.data); }); await Promise.all(promises); diff --git a/backend/storage/package-lock.json b/backend/storage/package-lock.json index 3b9a47e..8304e66 100644 --- a/backend/storage/package-lock.json +++ b/backend/storage/package-lock.json @@ -8,6 +8,7 @@ "name": "storage", "version": "0.0.0", "dependencies": { + "p-limit": "^6.1.0", "zod": "^3.23.4" }, "devDependencies": { @@ -894,6 +895,21 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@vitest/snapshot": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.0.tgz", @@ -1766,12 +1782,11 @@ } }, "node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", - "dev": true, + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", + "integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==", "dependencies": { - "yocto-queue": "^1.0.0" + "yocto-queue": "^1.1.1" }, "engines": { "node": ">=18" @@ -2970,10 +2985,9 @@ "dev": true }, "node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "engines": { "node": ">=12.20" }, diff --git a/backend/storage/package.json b/backend/storage/package.json index 8b210b7..3f5c39f 100644 --- a/backend/storage/package.json +++ b/backend/storage/package.json @@ -17,6 +17,7 @@ "wrangler": "^3.0.0" }, "dependencies": { + "p-limit": "^6.1.0", "zod": "^3.23.4" } } diff --git a/backend/storage/src/index.ts b/backend/storage/src/index.ts index c57e7e7..c9b371e 100644 --- a/backend/storage/src/index.ts +++ b/backend/storage/src/index.ts @@ -1,7 +1,9 @@ import { z } from "zod" +import pLimit from 'p-limit'; export interface Env { R2: R2Bucket + Templates: R2Bucket KEY: string } @@ -144,17 +146,18 @@ export default { console.log(`Copying template: ${type}`); - const templateDirectory = `templates/${type}`; - // List all objects under the directory - const { objects } = await env.R2.list({ prefix: templateDirectory }); + const { objects } = await env.Templates.list({ prefix: type }); - // Copy each object to the new directory - for (const { key } of objects) { - const destinationKey = key.replace(templateDirectory, `projects/${sandboxId}`); - const fileBody = await env.R2.get(key).then(res => res?.body ?? ""); + // Copy each object to the new directory with a 5 concurrency limit + const limit = pLimit(5); + await Promise.all(objects.map(({ key }) => + limit(async () => { + const destinationKey = key.replace(type, `projects/${sandboxId}`); + const fileBody = await env.Templates.get(key).then(res => res?.body ?? ""); await env.R2.put(destinationKey, fileBody); - } + }) + )); return success } else { diff --git a/frontend/app/(app)/code/[id]/page.tsx b/frontend/app/(app)/code/[id]/page.tsx index d97025b..9681a5b 100644 --- a/frontend/app/(app)/code/[id]/page.tsx +++ b/frontend/app/(app)/code/[id]/page.tsx @@ -6,6 +6,7 @@ import { notFound, redirect } from "next/navigation" import Loading from "@/components/editor/loading" import dynamic from "next/dynamic" import fs from "fs" +import { TerminalProvider } from "@/context/TerminalContext" export const revalidate = 0 @@ -87,8 +88,10 @@ export default async function CodePage({ params }: { params: { id: string } }) { } return ( + <>