رفتن به محتوا

پشتیبان‌گیری، برون‌بری و درون‌بری

همهٔ چیزهایی که Control Center می‌تواند کپی کند، دست‌به‌دست کند یا بپذیرد، و شکل دقیق هر آرتیفکت. برای اینکه واقعاً پشتیبان بگیرید، پشتیبان‌گیری و بازیابی را ببینید؛ برای اینکه چرا ماندگاری این‌طور تقسیم شده، فضاهای کاری و ایزوله‌سازی را ببینید.

سه آرتیفکت کپی پایگاه داده وجود دارد، با دامنه‌ها و سیاست‌های حذف متفاوت.

آرتیفکت نوشته‌شده توسط شکل پوشش
اسنپ‌شات نصب server.backupNow یک پوشهٔ زمان‌دار هر پایگاه داده روی این نصب
پشتیبان فضای کاری پایپ‌لاین Workspace backup پوشهٔ زمان‌دار با یک .db پایگاه دادهٔ یک فضای کاری
برون‌بری فضای کاری workspace.export یک فایل تک .db پایگاه دادهٔ یک فضای کاری

همه با VACUUM INTO مربوط به SQLite نوشته می‌شوند، که در برابر یک پایگاه دادهٔ زندهٔ WAL ایمن است: یک تراکنش خواندن می‌گیرد، نسخه‌ای یکپارچه‌سازی‌شده و از نظر تراکنشی سازگار تولید می‌کند، و هرگز مستلزم متوقف کردن سرور نیست.

<dataDir>/backups/2026-07-28T09-12-33-000Z/
manifest.json
global.db
<workspaceId>/workspace.db one directory per workspace

این چیدمان دقیقاً آینهٔ پوشهٔ دادهٔ زنده است، و همین است که بازیابی یک نصب را به یک کپی به عقب تبدیل می‌کند، نه یک ترجمه. نام پوشه، برچسب زمانی UTC است که : و . در آن با - جایگزین شده‌اند، پس روی Windows ایمن برای سامانهٔ فایل است و به‌شکل یک رشتهٔ ساده به‌ترتیب زمانی مرتب می‌شود.

پشتیبان‌های زمان‌بندی‌شدهٔ فضای کاری جداگانه در <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db زندگی می‌کنند. آن‌ها نه مانیفست دارند و نه global.db، و اسنپ‌شات نصب نیستند. گام نگهداشت پایپ‌لاین هفتگی فقط پشتیبان‌های قدیمی‌تر از سن پیکربندی‌شدهٔ همین فضای کاری را حذف می‌کند (به‌طور پیش‌فرض 30 روز)؛ اسنپ‌شات‌های نصب دستی هرگز با آن گام چرخش داده نمی‌شوند. server.listBackups فقط اسنپ‌شات‌های نصب را فهرست می‌کند، از جمله ناقص‌ها.

فیلد نوع معنا
version عدد صحیح نسخهٔ قالب مانیفست. هم‌اکنون 1
created_at ISO-8601 UTC زمان گرفتن اسنپ‌شات
global.file رشته همیشه global.db
global.schema_version عدد صحیح نسخهٔ اسکیمای GlobalDatabase در زمان گرفتن
global.bytes عدد صحیح اندازهٔ global.db نوشته‌شده
workspace_schema_version عدد صحیح نسخهٔ اسکیمای WorkspaceDatabase که میان همهٔ فایل‌های فضای کاری مشترک است
workspaces[] آرایه یک ورودی به‌ازای هر فضای کاری گرفته‌شده
workspaces[].workspace_id رشته فضای کاری‌ای که این فایل در خود دارد
workspaces[].file رشته مسیر نسبت به ریشهٔ اسنپ‌شات، <workspaceId>/workspace.db
workspaces[].bytes عدد صحیح اندازهٔ آن فایل
skipped_workspaces[] آرایهٔ رشته فضاهای کاری‌ای که پشتیبان نتوانست بگیرد

یک فضای کاری وقتی رد می‌شود که ثبت شده باشد اما هرگز چیزی در آن نوشته نشده باشد (پس هنوز فایلی وجود ندارد)، یا وقتی VACUUM INTO آن شکست خورده باشد. در هر حال اسنپ‌شات همچنان کامل می‌شود و مانیفست آنچه گم است را نام می‌برد.

server.listBackups به‌ازای هر اسنپ‌شات یک پرچم complete گزارش می‌کند. وقتی نادرست است که مانیفست غایب یا ناخوانا باشد، global.db گم باشد، یا مانیفست فایل فضای کاری‌ای را نام ببرد که روی دیسک نیست.

یک اسنپ‌شات ناقص همچنان فهرست می‌شود، چون اسنپ‌شاتی که اپراتور نمی‌بیند، همانی است که باور دارد داردش. وقتی مانیفست خواندنی نیست، فهرست به خود چیدمان برمی‌گردد و هر فایل <workspaceId>/workspace.db را که پیدا کند گزارش می‌کند — این‌ها از طریق workspace.import همچنان یکی‌یکی قابل پذیرش‌اند، هرچند کل اسنپ‌شات نمی‌تواند یک نصب را بازیابی کند.

چیزهایی که یک پشتیبان در بر ندارد

بخش با عنوان “چیزهایی که یک پشتیبان در بر ندارد”

هر دو آرتیفکت فقط پایگاه داده هستند. پوشهٔ یک فضای کاری بیش از پایگاه داده‌اش را در خود دارد، و هیچ‌یک از بقیه سفر نمی‌کند:

مسیر در اسنپ‌شات؟ در برون‌بری فضای کاری؟
global.db بله خیر
<workspaceId>/workspace.db بله بله (خودِ فایل است)
<workspaceId>/blobs/ خیر خیر
<workspaceId>/skills/ خیر خیر
<workspaceId>/agents/ خیر خیر
<workspaceId>/chat_credentials/ خیر خیر
<workspaceId>/spaces/<spaceId>/ خیر خیر
<workspaceId>/pr_clones/ خیر خیر
secrets.json خیر خیر
models/ خیر خیر
meetings/<meetingId>/ خیر خیر
rigs/ خیر خیر

بخشی از آن یک‌بارمصرف است — spaces/ در خود worktreeهای copy-on-write دارد که از مخزن‌ها از نو تأمین می‌شوند، pr_clones/ یک کش است، models/ از نو دانلود می‌شود، rigs/ وضعیت ماشین است. بخشی از آن این‌طور نیست: blobs/ تصاویر جای‌گذاری‌شده‌ای را در خود دارد که سطرهای پایگاه داده به آن‌ها اشاره می‌کنند، skills/ و agents/ فایل‌هایی را در خود دارند که یک عامل با آن‌ها اجرا می‌شود، و secrets.json هر کلید جفت‌سازی، اعتبارنامهٔ ارائه‌دهنده و تنظیم SSO روی نصب را در خود دارد. برای پوشش دادن بقیه، پشتیبان‌گیری و بازیابی را ببینید.

RPCهای پشتیبان‌گیری نصب و برون‌بری/درون‌بری فضای کاری فقط fullClient هستند: یک تلفن جفت‌شده نمی‌تواند آن‌ها را راه بیندازد. همه‌شان روی سروری که هیچ دروازهٔ پشتیبان‌گیری سیم‌کشی‌شده‌ای ندارد — مثل سرور دمو — کاملاً غایب‌اند، نه رد شده: از نظر ساختاری نیستند.

عملیات نوع دامنه کمترین نقش آرگومان‌ها برگشتی
server.backupNow تغییر نصب مالک نصب هیچ {ok, path}
server.listBackups خواندن نصب مالک نصب هیچ {backups: [...]}
server.deleteBackup تغییر نصب مالک نصب name {ok}
workspace.export خواندن فضای کاری admin هیچ {ok, path}
workspace.import تغییر فضای کاری owner source_path {ok, workspace_id}
workspace.delete تغییر نصب* owner id ردیف رجیستری حذف‌شده علامت‌گذاری می‌شود
  • workspace.delete بی‌دامنه است چون ردیفی که علامت می‌زند در رجیستری جهانی زندگی می‌کند؛ گرداننده‌اش عضویت فراخوان در فضای کاری نام‌برده را بررسی می‌کند و owner را لازم دارد.

path در هر پاسخ، مسیری روی میزبان سرور است.

تازه‌ترین اول، مرتب‌شده بر اساس نام پوشه (که همان برچسب زمانی است، پس ترتیب حتی برای اسنپ‌شاتی که مانیفستش خوانده نشده هم برقرار می‌ماند).

{
"backups": [
{
"path": "/…/backups/2026-07-28T09-12-33-000Z",
"name": "2026-07-28T09-12-33-000Z",
"created_at": "2026-07-28T09:12:33.000Z",
"bytes": 481203712,
"complete": true,
"workspaces": [
{
"workspace_id": "w_9f2c…",
"path": "/…/backups/2026-07-28T09-12-33-000Z/w_9f2c…/workspace.db",
"bytes": 190840832
}
],
"skipped_workspace_ids": []
}
]
}

created_at وقتی حذف می‌شود که مانیفست خوانده نشده باشد. bytes در سطح بالا اندازهٔ واقعی روی دیسک برای کل پوشه است، نه جمع خود مانیفست — پرسشی که اپراتوری هنگام هرس اسنپ‌شات‌ها می‌پرسد این است که پوشه چه هزینه‌ای دارد، نه اینکه پشتیبان قصد داشته چه بنویسد.

هر workspaces[].path دقیقاً همان چیزی است که workspace.import به‌عنوان source_path می‌گیرد. این عامدانه است: «این فضای کاری را از این اسنپ‌شات بازیابی کن» همان عملیات درون‌بری است، پس این دو نمی‌توانند به رفتارهای متفاوتی با یک فایل واحد بلغزند.

پیش از آنکه چیزی جایگزین شود، فایل نامزد به‌صورت فقط‌خواندنی با یک اتصال خام کوتاه‌عمر SQLite باز می‌شود و سطر workspace_meta آن خوانده می‌شود.

شرط نتیجه
پایگاه دادهٔ SQLite خواندنی نیست، یا workspace_meta وجود ندارد رد می‌شود. هیچ‌چیز دست نمی‌خورد
شناسهٔ فضای کاری ثبت‌شده ≠ هدف مجاز، ثبت می‌شود. این همان راهی است که یک فضای کاری تکثیر یا زیر شناسه‌ای تازه بازیابی می‌شود
شناسهٔ نصب ثبت‌شده ≠ این نصب مجاز، ثبت می‌شود. دستگاه‌های جفت‌شده و شناسه‌های کاربری‌اش به آن نصب تعلق دارند و اینجا حل نمی‌شوند
شناسهٔ فضای کاری نامعتبر، یا فایل وجود ندارد رد می‌شود

پس از پذیرش، پایگاه دادهٔ فضای کاری هدف بسته و از مدیر برداشته می‌شود، پیش از آنکه فایل رویش کپی شود (یک اتصال drift باز، فایل و -wal آن را نگه می‌دارد)، سپس دوباره باز می‌شود تا beforeOpen تریگرهای FTS و همگام‌سازی را از نو نصب کند، و ایندکس‌های FTS از نو ساخته می‌شوند — جدول‌های محتوای یک فایل درون‌برده‌شده پر می‌شوند اما ایندکسش ممکن است کهنه باشد.

هر عملیات بالا با مسیرهای سمت سرور حرف می‌زند، که فقط وقتی پاسخ کاملی است که سرور ماشین خودتان باشد. این سه، بایت‌ها را حمل می‌کنند، روی همان مسیر امضاشده با PSK که پروکسی رسانه و انبار blob استفاده می‌کنند. فراخوان یک رشتهٔ هدف را با کلید از پیش همرساندهٔ دستگاهش امضا می‌کند و امضا را به‌عنوان s می‌فرستد.

مسیر متد کوئری هدف امضاشده نیازمند
/backup/workspace GET w, d, s backup-workspace:<workspaceId> ادمین فضای کاری
/backup/snapshot GET n, d, s backup-snapshot:<name> مالک نصب
/backup/restore POST w, d, s backup-restore:<workspaceId> مالک فضای کاری

w یک شناسهٔ فضای کاری است، n یک نام پوشهٔ اسنپ‌شات، d شناسهٔ دستگاه فراخوان و s امضا. n در برابر فهرست پشتیبان‌ها حل می‌شود، نه اینکه به ریشهٔ پشتیبان‌ها پیوند بخورد، پس مسیر را نمی‌توان به پوشه‌ای نشانه گرفت که فهرست نشانش نمی‌داد.

کد وضعیت علت
400 یک پارامتر کوئری الزامی گم است، یا بدنهٔ آپلود خالی است
403 دستگاه ناشناخته یا باطل‌شده، امضای بد، یا فراخوان نقش لازم را ندارد
404 روی این میزبان دروازهٔ پشتیبان‌گیری وجود ندارد، یا اسنپ‌شات/فایل فضای کاری نام‌برده وجود ندارد
405 /backup/restore با چیزی جز POST فراخوانی شده است
413 بدنهٔ آپلود از 8 GiB فراتر می‌رود، چه با content-length اعلام‌شده و چه با بایت‌های واقعاً خوانده‌شده
500 برون‌بری یا آرشیو سمت سرور شکست خورد

هر دو دانلود با Cache-Control: no-store و Accept-Ranges: none پاسخ می‌دهند. هر درخواست یک نسخهٔ تازه ضرب می‌کند و پس از استریم شدن پاکش می‌کند، پس یک پاسخ کش‌شده یا ازسرگرفته‌شده بایت‌های دو برون‌بری مختلف را در فایلی به هم می‌بندد که سالم به نظر می‌رسد و نیست.

/backup/snapshot <name>.zip را برمی‌گرداند، با ورودی‌هایی نسبت به ریشهٔ اسنپ‌شات، تا باز کردنش manifest.json + global.db + <workspaceId>/workspace.db را بازتولید کند. ورودی‌ها به‌ترتیب مرتب نوشته می‌شوند، پس دو آرشیو از یک اسنپ‌شات، همان یک آرشیو هستند.

/backup/restore بدنه را مستقیم و بدون بافر کردن به یک فایل موقت استریم می‌کند، آن را پیش و در طول خواندن کران‌دار می‌کند، و فایل موقت را روی هر مسیر خروجی، از جمله رد شدن، پاک می‌کند.

مورد مقدار
اسنپ‌شات‌ها <dataDir>/backups/<timestamp>/
پشتیبان‌های زمان‌بندی‌شدهٔ فضای کاری <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db
برون‌بری‌های فضای کاری <dataDir>/backups/exports/<workspaceId>-<timestamp>.db
محوطهٔ موقت انتقال <dataDir>/backups/transfer/ — یک میزکار، که همان مسیری که می‌نویسدش جاروبش می‌کند
نام آرشیو اسنپ‌شات <snapshot directory name>.zip
سقف آپلود 8 GiB برای هر POST /backup/restore
نگهداشت اسنپ‌شات‌های نصب: حذف دستی. پشتیبان‌های فضای کاری: پایپ‌لاین هفتگی، پیش‌فرض 30 روز

پوشه‌های exports/، transfer/ و workspace-backups/ اسنپ‌شات نصب نیستند و از server.listBackups بیرون گذاشته می‌شوند. فقط پوشهٔ آخر نگهداشت زمان‌بندی‌شده دارد؛ حذف یک اسنپ‌شات نصب به اقدام صریح مالک نصب نیاز دارد.