Skip to content

שחזור גיבוי ממזג לוחות ואוספים שחולקים שם, כי השיוך הוא לפי שם ולא לפי מזהה #3309

Description

@amirbiron

הבעיה

שחזור גיבוי אישי משייך ישויות לפי שם, ושם אינו מפתח ייחודי בשום מקום במערכת. כשקיימים שני לוחות או שני אוספים באותו שם, השחזור ממזג אותם לאחד — בשקט, בלי שגיאה, ובלי שהמשתמש יידע.

זה נמצא בסבב ריוויוו על PR #3306 ולא תוקן שם, כי התיקון המלא דורש שינוי סכימה שחורג מהסקופ של אותו PR. פירוט למטה.

למה שני לוחות באותו שם הם מצב חוקי

אין ולידציית ייחודיות ב-create_board ולא ב-rename_board, ואין אינדקס ייחודי על השם. האינדקס היחיד על note_boards הוא one_default_per_user — ייחודי-חלקי על is_default: True בלבד.

בנוסף, normalize_board_name("") מחזיר את DEFAULT_BOARD_NAME, כך שאפשר להגיע לשני לוחות באותו שם גם בלי כוונה.

שתי שכבות, ולא אחת

לוחות_restore_note_boards בונה קבוצת שמות קיימים ומדלג על לוח שהשם שלו כבר קיים; _restore_board_note מוצא את הלוח לפי find_one({user_id, name}). כששני לוחות חולקים שם, השאילתה מחזירה אחד מהם באופן שרירותי וכל הפתקים של שניהם נוחתים עליו.

אוספים — אותו דפוס, וכאן הוא מעניין יותר: ב-_restore_collections המזהה המקורי של האוסף (old_id) כן נמצא בגיבוי, ובכל זאת existing_collections הוא מילון ממופתח בשם. כשבחשבון היעד יש שני אוספים באותו שם, המילון שומר את האחרון מביניהם — ו-old_to_new_id[old_id] מצביע על אוסף שנבחר שרירותית. כל הקבצים של האוסף מהגיבוי נכנסים לאוסף הלא נכון.

לוחות הם המקרה החמור יותר (אין old_id בכלל בגיבוי), אבל האוספים מראים שהשורש אינו חוסר מידע — אלא בחירה לשייך לפי שם.

למה זה לא תוקן ב-PR

התיקון שנראה מתבקש — לשמור את המזהה המקורי בגיבוי ולשייך לפיו — שובר אידמפוטנטיות. במסמך היעד אין שדה שמתעד מאיזה לוח בגיבוי הוא הגיע, ולכן שחזור שני של אותו גיבוי לא יזהה שהלוח כבר נוצר וייצור כפילות. כדי לשמור אידמפוטנטיות צריך שדה מוצא מתמיד על מסמך הלוח — כלומר שינוי סכימה, מחוץ לסקופ של PR שעוסק ב-created_at.

שתי דרכים אפשריות

בלי המלצה — שתיהן דורשות החלטה:

  1. אכיפת ייחודיות שם (אינדקס ייחודי + ולידציה ב-create_board/rename_board). פותר את השורש, אבל משנה התנהגות קיימת ודורש טיפול בכפילויות שכבר קיימות אצל משתמשים.
  2. שדה מוצא + מיפוי old_id ← new_id, כמו שכבר קיים לאוספים. משנה את פורמט הגיבוי ומוסיף שדה לסכימה, ומצריך תאימות לאחור לגיבויים ישנים.

הערה על תיקון חלקי

מיפוי old_id ← new_id בלי שדה מוצא היה משפר את השיוך רק ללוחות שהשחזור עצמו יצר. לוח שהותאם ללוח קיים עדיין נבחר לפי שם, ולכן שני לוחות קיימים באותו שם היו נשארים בעיה. שווה לדעת לפני שבוחרים מסלול שנראה זול.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions