ข้ามไปยังเนื้อหา

เวิร์กสเปซและการแยกโดเมน

เวิร์กสเปซคือผู้เช่าที่ใช้แยกโดเมนในระดับสูงสุดของ Control Center มันจัดกลุ่มเอเจนต์ รีโพสิทอรี สเปซ ตั๋วงาน หน่วยความจำ ไปป์ไลน์ และสมาชิกให้เป็นบริบทที่มีขอบเขต ทุกสิ่งที่เกิดขึ้นภายในเวิร์กสเปซจะอยู่ในเวิร์กสเปซนั้น

เวิร์กสเปซทั่วไปสอดคล้องกับหนึ่งโปรเจกต์หรือหนึ่งโค้ดเบส คุณอาจมีเวิร์กสเปซแยกกันสำหรับ “api-service”, “frontend-v2” และ “infrastructure”

แถวข้อมูลของเวิร์กสเปซอยู่ในไฟล์ SQLite ของเวิร์กสเปซนั้นเอง ที่ <dataDir>/<workspaceId>/workspace.db แต่ละเวิร์กสเปซได้ไดเรกทอรีหนึ่งไดเรกทอรีแทนที่จะเป็นไฟล์เปล่า ๆ เพราะเวิร์กสเปซสะสมมากกว่าฐานข้อมูล — worktree ประจำการสนทนา ไฟล์เอเจนต์และสกิล ข้อมูลรับรองของแชทบอต — และการให้โฟลเดอร์กับมันหมายความว่าทั้งหมดนั้นอยู่ร่วมกันและถูกลบไปพร้อมกัน

เอนทิตี ขอบเขต
เอเจนต์ สังกัดเวิร์กสเปซเดียวเท่านั้น
รีโพสิทอรี ลงทะเบียนเข้าเวิร์กสเปซเดียว (ดูด้านล่าง)
สเปซ การสนทนา และข้อความ ผูกกับเวิร์กสเปซ
ตั๋วงาน โปรเจกต์ แผน และการประสานงาน ผูกกับเวิร์กสเปซ
ข้อเท็จจริงในหน่วยความจำ นโยบาย โดเมน และสิทธิ์การเข้าถึง ผูกกับเวิร์กสเปซ
รันไปป์ไลน์ เทมเพลต และทริกเกอร์ ผูกกับเวิร์กสเปซ
สถานะ pull request สเปซรีวิว และ cohort รีวิว ผูกกับเวิร์กสเปซ
ล็อกรันของเอเจนต์และหน่วยความจำใช้งาน ผูกกับเวิร์กสเปซ
สมาชิก คำเชิญ และสิทธิ์รายรีโป ผูกกับเวิร์กสเปซ
สัญลักษณ์และเส้นเชื่อมของกราฟโค้ด ผูกด้วย repoId ภายในไฟล์เวิร์กสเปซ

แถวข้อมูลเหล่านี้ส่วนใหญ่มีคอลัมน์ workspaceId ส่วนไฟล์ฐานข้อมูลที่แยกจากกันเป็นตัวบังคับใช้การแยกโดเมน ดูค่าคงที่ของการแยกโดเมนด้านล่าง

รีโปผูกกับเวิร์กสเปซ ส่วนตัวตนข้ามเวิร์กสเปซยึดตามเส้นทาง

หัวข้อที่มีชื่อว่า “รีโปผูกกับเวิร์กสเปซ ส่วนตัวตนข้ามเวิร์กสเปซยึดตามเส้นทาง”

แถวข้อมูลของรีโปอยู่ในไฟล์ฐานข้อมูลของเวิร์กสเปซเอง — ไฟล์_คือ_ขอบเขต ดังนั้นตารางจึงไม่มีคอลัมน์ workspaceId และไม่มีตารางเชื่อม

คุณเพิ่มรีโปเข้าเวิร์กสเปซได้ที่ การตั้งค่า → เวิร์กสเปซ → รีโพสิทอรี การลงทะเบียนเช็คเอาต์เดียวกันในสองเวิร์กสเปซจะสร้างสองแถวที่เป็นอิสระต่อกันพร้อมสองไอดี ส่วนตัวตนของรีโป_ข้าม_เวิร์กสเปซยึดตามเส้นทางในระบบไฟล์ (หรือ owner/name บน GitHub) ไม่ใช่ไอดีเด็ดขาด

การลงทะเบียนเข้มงวด: เส้นทางต้องอยู่ภายใน work tree ของ git ต้องมี remote ชื่อ origin และ remote นั้นต้องชี้ไปที่ forge ที่รองรับ (github.com, gitlab.com หรือ bitbucket.org) ระบบอ่าน forge จาก remote และเก็บไว้บนรีโป ดังนั้นเวิร์กสเปซเดียวจึงเก็บรีโปจากทั้งสามแห่งได้ สิ่งอื่นใดจะถูกปฏิเสธ ตัวเรียกดูโฟลเดอร์ที่คุณใช้เลือกจะแสดงระบบไฟล์ของโฮสต์เซิร์ฟเวอร์ โดยจำกัดอยู่ที่ allow-list --repo-roots ของเซิร์ฟเวอร์ (ซึ่งค่าเริ่มต้นคือโฮมไดเรกทอรีของผู้ใช้ที่รันเซิร์ฟเวอร์)

การลบรีโพสิทอรีออกจากเวิร์กสเปซจะลบแถวนั้นทิ้งไปเลย และลบต่อเนื่องไปยังสัญลักษณ์โค้ด เส้นเชื่อม ไฟล์ จุดตรวจของดัชนี และสิทธิ์รายสมาชิกของมัน ส่วนเช็คเอาต์บนดิสก์ไม่ถูกแตะต้อง

กราฟโค้ดอยู่ในไฟล์เดียวกัน โดยมีคีย์เป็น repoId เพราะเวิร์กสเปซต่าง ๆ อาจมีรีโพสิทอรีเดียวกันบนสาขาต่างกันซึ่งมีโค้ดต่างกัน

การรั่วไหลของข้อมูลข้ามเวิร์กสเปซถือเป็นบั๊ก การแยกโดเมนเป็นเรื่องเชิงโครงสร้าง ซึ่งบังคับใช้ในหลายระดับ:

  • ชั้นฐานข้อมูล แต่ละเวิร์กสเปซมีไฟล์ SQLite ของตัวเอง ซึ่งส่งมอบโดย WorkspaceDatabaseManager.of(workspaceId) ฐานข้อมูลของเวิร์กสเปซไม่ได้ประกาศตาราง users, workspaces หรือตารางของเวิร์กสเปซอื่น ดังนั้นการอ่านข้ามเวิร์กสเปซจึงไม่ใช่บั๊กที่คุณเขียนขึ้นได้ — มันคอมไพล์ไม่ผ่าน รีโพสิทอรีรีโซลฟ์ DAO ของตัวเองในแต่ละครั้งแทนที่จะแคชไว้หนึ่งตัว และเนื่องจากทุกเมธอดของรีโพสิทอรีรับ workspaceId แบบบังคับ เวิร์กสเปซจึงถูกอนุมานหรือใช้ค่าเริ่มต้นไม่ได้เลย
  • ไอดีของเวิร์กสเปซเป็นส่วนหนึ่งของเส้นทาง เพราะไอดีกลายเป็นชื่อไดเรกทอรี มันจึงต้องตรงกับรูปแบบ single-segment ที่ปลอดภัย (เริ่มด้วยตัวอักษรหรือตัวเลข ตามด้วยตัวอักษรหรือตัวเลข จุด ขีดล่าง ขีดกลาง; ห้ามมี ..) ไอดีเป็น UUID ทุกที่ในผลิตภัณฑ์ สิ่งอื่นใดจะ throw แทนที่จะถูกทำให้ปลอดภัย — นั่นคือด่านกัน path traversal และมันล้มเหลวอย่างเสียงดังแทนที่จะเขียนข้อมูลของเวิร์กสเปซไปยังเส้นทางที่คนอื่นเลือก
  • การป้องกันหลายชั้น คอลัมน์ workspaceId ยังอยู่ตรงนั้นและยังถูกเขียนอยู่ แม้จะซ้ำซ้อนภายในไฟล์เดียว แต่มันทำให้ทริกเกอร์ของ sync-feed ดัชนี FTS และรูปทรงของแถวที่มีอยู่ไม่เปลี่ยนแปลง และทำให้ไฟล์อธิบายตัวเองได้เมื่อถูกตรวจดูเดี่ยว ๆ — ซึ่งเป็นสิ่งที่การส่งออกและการนำเข้าพึ่งพา
  • ชั้นโดเมน บริการที่กลายพันธุ์เอนทิตีตามไอดีจะตรวจสอบ entity.workspaceId == workspaceId ที่จุดควบคุมจุดเดียวเดียวก่อนดำเนินการ และ throw WorkspaceMismatchException เมื่อไม่ตรงกัน — ความล้มเหลวแบบเสียงดังสำหรับไอดีที่มาจากบริบทผิด การปฏิเสธอย่างเสียงดังสำคัญ เพราะการเงียบไม่ทำอะไรเลยซ่อนบั๊กไว้ ส่วนการดำเนินการต่อไปคือการรั่วไหล
  • ชั้น RPC ตัวจัดส่ง repo-RPC คือจุดควบคุม ทุก op ที่ผูกกับเวิร์กสเปซต้องพก workspace_id ไว้ใน args ของตัวเอง — ไม่มี “เวิร์กสเปซปัจจุบัน” ระดับเซสชันให้รั่วไหล และไอดีที่ไม่รู้จักจะถูกปฏิเสธว่าไม่พบ ก่อน ที่อะไรจะเปิดฐานข้อมูล ดังนั้นไอดีที่ไม่ดีจึงก่อร่าง workspace.db ผีขึ้นมาไม่ได้ ops ที่เป็นระดับส่วนกลางจริง ๆ (ฟีดข่าว คิวของฟลีต) ประกาศตัวเองว่าไม่ผูกกับเวิร์กสเปซ ซึ่งเป็นการตัดสินใจที่ชัดเจนและผ่านการทบทวนแล้ว เครื่องมือ MCP ก็ใช้กฎเดียวกัน: เครื่องมือใดที่แตะข้อมูลซึ่งผูกกับเวิร์กสเปซต้องมี workspace_id
  • การกระจายข้ามเวิร์กสเปซนับแจกแจงได้ การตอบคำถามเกี่ยวกับเวิร์กสเปซหลายตัวหมายถึงการเปิดฐานข้อมูลหลายตัว การกระจายนั้นถูกจำกัดให้อยู่ที่ตัวช่วยตัวเดียว CrossWorkspaceQueries รายการทั้งหมดของสิ่งที่ข้ามขอบเขตอย่างชอบธรรมจึงอยู่ในจุดเรียกใช้ของไฟล์เดียว แทนที่จะกระจายไปอยู่หลังคอมเมนต์อธิบาย จุดเรียกใช้เหล่านั้นได้แก่: การรวบรวมข้อมูลระดับทั้งเซิร์ฟเวอร์ ตัวกระทบยอดตอนเริ่มระบบ การกวาดตามอายุการเก็บและ GC การสำรองข้อมูล ตัวจัดเส้นทางเหตุการณ์ — และการค้นหาสมาชิกภาพด้านล่าง
  • การเข้าถึงด้วยไอดีอย่างเดียวไม่เพียงพอ การค้นหาเอนทิตีด้วย UUID ไม่ได้พิสูจน์ว่ามันเป็นของเวิร์กสเปซของผู้เรียก การแยกไฟล์ทำให้ไฟล์ที่ผิดเข้าถึงไม่ได้ ส่วนการตรวจสอบในชั้นโดเมนจับไอดีที่ผิดซึ่งมาทางไฟล์ที่ชอบด้วยกฎหมาย

สมาชิกภาพต่างหากที่ให้สิทธิ์ ไม่ใช่คีย์จับคู่

หัวข้อที่มีชื่อว่า “สมาชิกภาพต่างหากที่ให้สิทธิ์ ไม่ใช่คีย์จับคู่”

การถือข้อมูลรับรองของอุปกรณ์เป็นการยืนยันตัวตนของ_อุปกรณ์_เท่านั้น ไม่ได้ให้อำนาจใด ๆ ภายในเวิร์กสเปซ ทุก op ที่ผูกกับเวิร์กสเปซจะรีโซลฟ์บทบาทสมาชิกภาพของผู้เรียกและบังคับใช้ขั้นต่ำที่ได้มาจากชนิดของ op — การอ่านต้องใช้ guest การกลายพันธุ์ต้องใช้ member การดำเนินการที่ทำลายได้ต้องใช้ admin — และ op ที่เปิดเผยเนื้อหารีโปจะตรวจสิทธิ์รายรีโปของผู้เรียกเพิ่มเติม คีย์จับคู่ที่ถูกต้องแต่ไม่มีสมาชิกภาพจะได้ Not a member of this workspace

ผลที่ตามมาต่อการแยกโดเมนนั้นเรียบง่าย: แถวสมาชิกภาพอยู่ในไฟล์_ของเวิร์กสเปซเอง_ ดังนั้น “ใครอยู่ในเวิร์กสเปซนี้?” จึงเป็นการอ่านแบบมีขอบเขตตามปกติ ส่วนคำถามกลับกัน — “ฉันอยู่ในเวิร์กสเปซใดบ้าง?” — ตามนิยามแล้วกระจายอยู่ตามไฟล์ต่าง ๆ จึงเป็นหนึ่งในการกระจายผ่าน CrossWorkspaceQueries ไม่กี่อย่างที่ได้รับอนุญาต และเป็นสิ่งที่ตัวเลือกเวิร์กสเปซรันก่อนจะมีการเลือกเวิร์กสเปซใด ๆ

ดูการทำงานร่วมกันแบบหลายคน สำหรับลำดับขั้นของบทบาทและสิทธิ์รายรีโป

ไม่ใช่ทุกอย่างจะผูกกับเวิร์กสเปซ ฐานข้อมูลตัวที่สอง <dataDir>/global.db เก็บสิ่งที่ระดับทั้งเซิร์ฟเวอร์จริง ๆ:

  • ทะเบียนเวิร์กสเปซ เพื่อให้ตัวสลับแสดงรายการเวิร์กสเปซทุกตัวได้โดยไม่ต้องเปิดไฟล์เวิร์กสเปซแม้แต่ไฟล์เดียว — และเพื่อให้ชื่อ โลโก้ เจ้าของ ลำดับในคู่มือ และเครื่องหมายลบแบบซอฟต์ของเวิร์กสเปซอยู่ภายนอกไฟล์ที่มันบรรยาย;
  • ตัวตน: ผู้ใช้ ค่ากำหนดของผู้ใช้ และอุปกรณ์ที่จับคู่ เพราะมนุษย์หนึ่งคนคือผู้ใช้หนึ่งคนในทุกเวิร์กสเปซ และอุปกรณ์ที่จับคู่แล้วจะอยู่รอดแม้เวิร์กสเปซถูกลบ;
  • คิวของฟลีต (วอร์กเกอร์ งาน ล็อกการจัดวาง) ซึ่งตัวจัดกำหนดการจะจับคู่ทั้งคิวกับวอร์กเกอร์ทุกตัวในแต่ละรอบ;
  • ฟีดข่าว ซึ่งเป็นรายผู้ใช้ (ไม่ใช่รายเวิร์กสเปซ) — การเพิ่มฟีดจะติดตามคุณไปทุกเวิร์กสเปซ;
  • workspace_routes ดัชนีก่อนการยืนยันตัวตนที่ตอบคำถาม “คีย์นี้เป็นของเวิร์กสเปซใด?” สำหรับจุดเข้าที่มาพร้อมเพียงความลับหรือไอดีทึบแสง (แฮชคำเชิญ โทเค็น webhook หรือลิงก์ตรง) และไม่มีเวิร์กสเปซเลย การไม่พบที่นั่นคือคำตอบแบบไม่พบ โดยเจตนาไม่มีทางถอยไปสแกนหา;
  • การตั้งค่าและตัวตนระดับทั้งการติดตั้ง: ไอดีการติดตั้ง การตั้งค่าระดับโฮสต์ การเชื่อมต่อ SSO และนโยบายการกระทำแบบมีการจัดการ (กลไกจำกัดระดับทั้งการติดตั้งที่ทำได้เพียงรัดกุมขึ้นเท่านั้น)

การบูตเปิดเฉพาะไฟล์นี้ ไฟล์เวิร์กสเปซเปิดแบบ lazy เมื่อถูกแตะครั้งแรก ต้นทุนการเริ่มระบบจึงคงที่ ไม่ว่าเวิร์กสเปซจะสะสมประวัติไว้มากเพียงใด และ quick_check ต่อไฟล์จะถูกจ่ายตอนใช้งานครั้งแรก ไม่ใช่บนเส้นทางไปสู่แบนเนอร์พร้อมใช้งาน

ไฟล์เวิร์กสเปซมีเพียง workspace_meta แถวเดียวสำหรับระบุตัวเอง (ไอดีของมัน การติดตั้งที่สร้างมัน เวอร์ชันสคีมาที่ใช้ตอนสร้าง และเวลาที่สร้าง) ทุกอย่างที่บรรยายเกี่ยวกับเวิร์กสเปซอยู่ในทะเบียน

การสร้างเวิร์กสเปซทำมากกว่าแค่แทรกแถวในทะเบียน ในปฏิบัติการเดียว เซิร์ฟเวอร์จะประทับผู้ใช้ที่สร้างเป็น ownerUserId บันทึกสมาชิกภาพบทบาทเจ้าของของผู้ใช้รายนั้น และเผยแพร่เหตุการณ์โดเมน WorkspaceCreated จากนั้นตัวรับฟังของเหตุการณ์นั้นจะ seed ต่อแบบ idempotent และในเบื้องหลัง:

  • เอเจนต์ CEO หนึ่งตัวพร้อมผู้เชี่ยวชาญอีกสี่ตัว — qa, architect, engineer, librarian — โดยผู้เชี่ยวชาญรายงานต่อ CEO;
  • เทมเพลตไปป์ไลน์ที่มีมาให้ในตัว และทริกเกอร์ของมัน (ทริกเกอร์แบบเหตุการณ์และแบบทำมือติดตั้งมาโดยเปิดใช้งานแล้ว ส่วนแบบตามกำหนดเวลาต้องเลือกเปิดเอง ยกเว้นการกวาด worktree-GC ประจำวัน);
  • ชุดการประเมินเริ่มต้น

สิ่งนี้เกิดขึ้นกับ_ทุก_เวิร์กสเปซ ไม่ใช่แค่เวิร์กสเปซแรก เอเจนต์ที่ถูก seed ถูกสร้างขึ้นโดยไม่มีอะแดปเตอร์ ดังนั้นจึงรันบน Control Center (built-in) ด้วยโมเดลเริ่มต้นของ Anthropic (claude-opus-4-8 เว้นแต่คุณจะปักหมุดโมเดลอื่น) จนกว่าคุณจะตั้งค่าอะแดปเตอร์และโมเดลต่อเอเจนต์ที่ การตั้งค่า → เวิร์กสเปซ → เอเจนต์ ดูโมเดลเอเจนต์

การเขียนสมาชิกภาพของเจ้าของสำคัญกว่าที่เห็น: หากไม่มีมัน เวิร์กสเปซที่เพิ่งสร้างจะไม่มีสมาชิกเลย และทุกการเรียกที่ผูกกับเวิร์กสเปซที่ผู้สร้างทำต่อไปจะถูกปฏิเสธ

การลบเวิร์กสเปซ ทำเครื่องหมายที่แถวในทะเบียนและยกเลิกการเชื่อมไดเรกทอรี เวิร์กสเปซหายไปจากทุกรายการและการค้นหา แถวในทะเบียนยังอยู่ (ถูกลบแบบซอฟต์) ดังนั้นไอดีจึงยังเป็นที่รู้จักของระบบสำรองข้อมูลและงานบำรุงรักษา แต่ workspace.delete จะทิ้งไดเรกทอรีของเวิร์กสเปซนั้นทันที — ฐานข้อมูล worktree ไฟล์เอเจนต์ และอื่น ๆ — ผ่าน WorkspaceDatabaseManager.dropAndClose มีเพียงเจ้าของเวิร์กสเปซเท่านั้นที่ลบได้

เพราะหนึ่งเวิร์กสเปซคือหนึ่งไฟล์ การส่งต่อเวิร์กสเปซจึงเป็นปฏิบัติการไฟล์ ไม่ใช่การดัมป์ทีละตาราง:

  • workspace.export คือ VACUUM INTO ครั้งเดียว — สแนปช็อตที่สอดคล้องและจัดเรียงข้อมูลใหม่ ซึ่งถ่ายภายใต้ทรานแซกชันแบบอ่าน ขณะที่เซิร์ฟเวอร์ยังให้บริการอยู่
  • workspace.import รับไฟล์แบบนั้นเข้ามาแทนที่ทุกสิ่งที่เวิร์กสเปซปลายทางถืออยู่ workspace_meta ที่ฝังอยู่ทำให้การนำเข้าแยกได้ว่า “ไฟล์ของฉันเองที่รับกลับมา” กับ “ไฟล์จากการติดตั้งอื่น” (อย่างหลังอนุญาต แต่จะถูกบันทึกไว้แทนที่จะมองไม่เห็น)
  • server.backupNow ถ่ายสแนปช็อตทั้งการติดตั้งลงไดเรกทอรีที่ประทับเวลา ซึ่งสะท้อนไดเรกทอรีข้อมูลจริง — manifest.json, global.db และ <workspaceId>/workspace.db หนึ่งไฟล์ต่อเวิร์กสเปซ — ดังนั้นการกู้คืนคือการคัดลอกกลับมา
  • server.listBackups อ่านไดเรกทอรีนั้นกลับมา โดยเรียงใหม่สุดก่อน พร้อมขนาดและรายการเวิร์กสเปซของแต่ละสแนปช็อต สแนปช็อตที่แมนิเฟสต์หายไปหรือระบุชื่อไฟล์ที่ไม่มีอยู่จริงจะยังถูกรายงานโดยทำเครื่องหมายว่าไม่สมบูรณ์ — การซ่อนมันไว้คือหนทางที่ผู้ดำเนินการจะเชื่อว่าตนมีข้อมูลสำรองทั้งที่ไม่มี

การดำเนินการสำรองข้อมูลอยู่ภายใต้ การตั้งค่า → เซิร์ฟเวอร์ → สำรองและกู้คืน: สำรองตอนนี้ ถ่ายสแนปช็อตของการติดตั้ง รายการจะแสดงว่าสแนปช็อตใด สมบูรณ์และให้เจ้าของการติดตั้งลบสแนปช็อตได้หลังยืนยัน และแต่ละเวิร์กสเปซมี การส่งออกและการนำเข้าให้ใช้ ไปป์ไลน์ Workspace backup ที่มีมาให้ในตัวจะถ่ายเฉพาะ ฐานข้อมูลของเวิร์กสเปซนั้นตามกำหนดรายสัปดาห์ และลบข้อมูลสำรองของตัวเองที่เก่ากว่า อายุการเก็บที่กำหนด การกู้คืนเวิร์กสเปซจากสแนปช็อตของการติดตั้งคือ workspace.import ที่ชี้ไปยัง <workspaceId>/workspace.db ของสแนปช็อตนั้น ส่วนการกู้คืนทั้งการติดตั้งยังคง เป็นการคัดลอกไดเรกทอรีสแนปช็อตกลับในขณะที่เซิร์ฟเวอร์หยุดทำงาน

สิ่งที่ไม่มีตัวใดพกไปด้วยคือส่วนที่เหลือของไดเรกทอรีเวิร์กสเปซ เวิร์กสเปซสะสมมากกว่าฐานข้อมูล — ภาพที่วางไว้ ไฟล์สกิลและเอเจนต์ ข้อมูลรับรองของแชท worktree — และการส่งออกกับการนำเข้าย้ายแค่ไฟล์ ทุกอย่างที่อยู่ข้าง ๆ จึงอยู่ที่เดิม การทำเช่นนี้เป็นเจตนาสำหรับข้อมูลรับรอง และเป็นเรื่องทิ้งได้สำหรับ worktree ส่วนที่เหลือนั้นเป็นขีดจำกัดที่ควรรู้ ไม่ใช่ฟีเจอร์ ข้อมูลอ้างอิงการสำรองข้อมูล มีตารางแบบเต็ม

การย้ายข้อมูลสำรองระหว่างเซิร์ฟเวอร์กับอุปกรณ์ของคุณ

หัวข้อที่มีชื่อว่า “การย้ายข้อมูลสำรองระหว่างเซิร์ฟเวอร์กับอุปกรณ์ของคุณ”

ทุก op ข้างต้นพูดถึงเส้นทางบนเซิร์ฟเวอร์ ซึ่งเป็นคำตอบที่ครบถ้วนเฉพาะเมื่อเซิร์ฟเวอร์คือเครื่องของคุณเอง เส้นทาง HTTP ที่ลงนามแล้วสามเส้นทาง — /backup/workspace, /backup/snapshot และ /backup/restore — ขนย้ายไบต์ให้กับทุกโทโพโลยีอื่น บนเลนที่ผ่านการยืนยันตัวตนแบบเดียวกับที่พร็อกซีสื่อและที่เก็บภาพใช้อยู่แล้ว บนหน้าเว็บ นี่คือปุ่ม ดาวน์โหลด ข้าง ๆ การส่งออกแต่ละรายการและสแนปช็อตแต่ละรายการ (คุณเลือกได้ว่าจะให้ไปลงที่ไหน) และ เลือกไฟล์แล้วอัปโหลด เพื่อกู้คืนจากไฟล์ที่อยู่ในเครื่องที่คุณกำลังใช้อยู่ การอัปโหลดคือวิธีที่ใช้ได้เมื่อเซิร์ฟเวอร์ไม่ใช่เครื่องของคุณ: workspace.import ต้องการให้ไฟล์อยู่บนโฮสต์แล้ว และนี่คือวิธีที่มันไปถึงที่นั่น

มีคุณสมบัติสามข้อที่ควรรู้:

  • การดาวน์โหลดสร้างสำเนาใหม่และเซิร์ฟเวอร์ไม่เก็บมันไว้เลย การดาวน์โหลดไม่ใช่ “ดึงไฟล์ที่ปุ่มส่งออกสร้างไว้” — มันส่งออกใหม่อีกครั้ง สตรีมสำเนานั้น แล้วลบทิ้ง คำตอบกลับเป็น no-store พร้อม Accept-Ranges: none ด้วยเหตุผลเดียวกัน: การสตรีมต่อช่วงที่ค้างไว้จะเชื่อมการส่งออกสองครั้งที่ต่างกันเข้าเป็นไฟล์เดียวที่ดูเหมือนถูกต้องแต่ไม่ใช่
  • การอัปโหลดถูกสตรีมลงดิสก์ ไม่ถูกบัฟเฟอร์เลย ทั้งสองฝั่ง และสำเนาที่พักไว้จะถูกลบในทุกเส้นทางที่ออกไป — รวมถึงกรณีถูกปฏิเสธ ฐานข้อมูลของเวิร์กสเปซไม่ใช่ภาพหน้าจอ
  • การเชื่อมต่อผ่านรีเลย์ไม่มี origin ของ HTTP ตัวควบคุมการถ่ายโอนจึงถูกปิดใช้งานที่นั่น พร้อมข้อความอธิบายเหตุผล ทุกสิ่งที่พูดถึงเส้นทางฝั่งเซิร์ฟเวอร์ยังทำงานผ่านรีเลย์ต่อไป มีเพียงเลนไบต์เท่านั้นที่ต้องเชื่อมต่อตรง

คุณสามารถรันเวิร์กสเปซหลายตัวเคียงข้างกันได้ แต่ละตัวทำงานอย่างอิสระ: เอเจนต์ในเวิร์กสเปซหนึ่งส่งข้อความถึงเอเจนต์ในอีกเวิร์กสเปซไม่ได้ อ่านหน่วยความจำของเวิร์กสเปซอื่นไม่ได้ และมองไม่เห็นตั๋วงานของมัน การหาผู้รับสำหรับการส่งข้อความระหว่างเอเจนต์เป็นแบบตรงตัวและไม่ข้ามเวิร์กสเปซเด็ดขาด

ไม่มีแดชบอร์ดข้ามเวิร์กสเปซ พื้นผิวการวิเคราะห์ที่ /workspaces/:workspaceId/observability สมัครรับฟีดส่วนกลางที่มีขอบเขตของรันล่าสุด แล้วจำกัดวงลงทันทีเหลือเฉพาะเวิร์กสเปซที่ใช้งานอยู่ สิ่งที่คุณเห็นที่นั่นจึงเป็นเวิร์กสเปซทีละตัว พื้นผิวที่มีหลายเวิร์กสเปซจริง ๆ เท่าที่คนทั่วไปแตะมีเพียงตัวเลือกเวิร์กสเปซกับตัวสลับ

มีขีดจำกัดในทางปฏิบัติข้อหนึ่งที่ควรรู้: เวิร์กสเปซที่มีคนใช้งานอยู่จะเปิดค้างไว้ — ไม่มี LRU เมื่อเกิน 32 ตัว เซิร์ฟเวอร์จะเตือนแทนที่จะปฏิเสธ เพราะไฟล์ที่เปิดอยู่แต่ละไฟล์ถือไอโซเลตเบื้องหลังและเพจแคชไว้ การกระจายข้ามเวิร์กสเปซเปิดไฟล์ชั่วคราวแล้วปิดในภายหลังหากไม่มีอย่างอื่นอ้างสิทธิ์มันไว้