פריסת חוזים חכמים ב-Near: צווארי בקבוק ותקלות
פריסת חוזים חכמים ב-Near — זו לא פעולה אחת, אלא שתיים בלתי תלויות: העלאת הקוד לאחסון החשבון וקריאה למתודת האתחול שיוצרת את המצב. סדר ידני נשבר באופן צפוי: הקוד עודכן, אך סכימת המצב שלו — לא.
החוזה מפורסם בהצלחה, אבל הקריאה הראשונה נכשלת בפענוח הנתונים המאוחסנים, והחשבון נשאר במצב שאין ממנו יציאה תקינה.
הקטגוריה השנייה של תקלות — בנייה. אם גרסת המהדר, מערך התלויות ופרמטרי האופטימיזציה אינם מקובעים, אותו קוד מקור מניב ארטיפקטים שונים. בנייה בלתי ניתנת לשחזור משמעה שלא ניתן להשוות את הקוד שפורסם למאגר: אי אפשר לאשר את היעדר שינויים זרים, וגם לא לבנות בדיוק את אותה גרסה לצורך חזרה.
השלישית — גישה. מפתחות החשבון שתחתם בוצעה הפרסום חיים לעתים קרובות בהיסטוריית הפקודות, בהתכתבות או במחשב של מהנדס אחד. אובדן מפתחות החשבון לא עוצר חוזה שכבר פועל, אבל סוגר את אפשרות העדכון: החשבון נשאר ללא בעלים, ואין במה להחזיר את השליטה.
בנפרד — היעדר חזרה לאחור. פרסום ברשת הראשית הוא בלתי הפיך, ואם הקוד הקודם לא נשמר ולא נבדק ברשת בדיקה, שגיאת פרסום החוזה צפה כבר אצל משתמשים חיים. להלן נפרט כיצד זה נסגר.
מה נותנת פריסה מנוהלת: מהירות וצפיות
פריסה מנוהלת מתחילה בבנייה ניתנת לחזרה: אותו קוד מקור ותלויות מקובעות מניבים ארטיפקט זהה, ולכן מה שנבדק ברשת הבדיקה עובר לרשת הראשית ללא אי-התאמות.
הזמן עד להרצה עובדת בסביבה נקייה נכנס למעבר אחד — הכנת חשבונות, פרסום ואתחול המצב מתבצעים לפי סדר שהוגדר מראש, ולא לפי הזיכרון של המבצע.
שיעור הפרסומים הכושלים ברשת Near יורד ראשון. לפני הכנסת סדר, כשל בערך כל ניסיון שלישי: החשבון לא נוצר, המפתח לא נכון, באחסון אין מספיק כיסוי למצב החוזה. כעת הבדיקות הללו עוברות לפני שליחת העסקה, ולרשת הראשית עובר רק מה שכבר עבד על עותק.
זמן ההתאוששות לאחר תקלה מתקצר משעות לעשרות דקות. ידוע איזה ארטיפקט פרוס, איזה מצב מתאים לו ולאיזו גרסה אפשר לחזור — החזרה לאחור הופכת לפעולה במקום חקירה.
יחד עם זה נעלם סוג שלם של כשלים: כתובות חשבון שגויות, מיגרציות מצב שלא הושלמו, שינויים ידניים שלא נכנסו להיסטוריה. הפריסה מפסיקה להיות אירוע מלחיץ והופכת לשלב שגרתי שאפשר להטיל על מהנדס תורן.
מצבי פריסה: השוואת גישות ומגבלות
מצבי הפריסה נבדלים לא בכלי ההרצה, אלא במי יוזם את הפרסום ומה קורה באותו רגע לנתוני החוזה. הקוד מתעדכן בפעולה אחת, והמצב נשאר כשהיה — אם מבנה הרשומות השתנה, הקוד החדש מתחיל לקרוא נתונים לא תואמים. לכן ברשת Near בחירת המצב נקבעת לפי שלושה פרמטרים: הפיכות, דרישות גישה ומחיר הטעות.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| פרסום ידני מסביבה מקומית | הרצה ראשונה, ניפוי שגיאות, שינויים חד-פעמיים | הכול תלוי במחשב של המהנדס: מפתחות וגרסת בנייה לא מקובעים בשום מקום, החזרה אינה משוחזרת |
| צינור פרסום | מהדורות סדירות, בדיקות לפני פרסום, מספר סביבות | דורש גישות מאובטחות בסביבת הבנייה; בנייה שגויה עוברת בלי השהיה לאישור |
| עדכון לפי סכימת המצב | מבנה הנתונים המאוחסנים משתנה | נדרש שלב נפרד של העברת מצב, עותק לפני הרצה ובדיקת שלמות ההעברה |
| החלפת חשבון | הבעלים משתנה או נדרשת כתובת נקייה | נתונים בין חשבונות אינם מועברים אוטומטית, ההיסטוריה הישנה והקישורים החיצוניים מאבדים רלוונטיות |
לעתים קרובות משלבים בין המצבים במקום לבחור אחד: הקוד עובר דרך הצינור, העברת המצב מתבצעת בשלב נפרד עם עותק מקדים, והחלפת החשבון מתוכננת כקמפיין נפרד — עם תקופה שבה שתי הכתובות פועלות במקביל והתעבורה מועברת בהדרגה.
שלבי העבודה ההנדסית: מביקורת ועד מסירה
את התהליך בונים כך שעדכון החוזה יצא באופן צפוי, ולא יהיה צורך לבנות מחדש את המצב ידנית. דילוג על ביקורת סכימת האחסון או הרשאות המפתחות צף בדרך כלל רק לאחר הפריסה ברשת הראשית — כשהתיקון עולה ביוקר.
- ביקורת קוד וסכימת אחסון. מנתחים את מבנה המצב: אילו שדות נשארים ללא שינוי, מה ידרוש מיגרציה, כמה אחסון תופס בחשבון החוזה. מתעדים מקומות שבהם העדכון ישפיע על נתונים שכבר נכתבו.
- סכימת חשבונות ותפקידים. ב-Near החשבון הוא החוזה עצמו, לכן מפרידים הרשאות: תת-חשבונות לחוזים, מפתח נפרד לפריסה, מפתחות פונקציונליים רק לקריאה למתודות מסוימות. החלפת קוד וחיוב יתרה באותו מפתח אינן משולבות.
- בנייה ניתנת לשחזור. מגדירים פרמטרי מהדר וסדר יצירת הארטיפקט, כך שכל מהנדס יקבל תוצאה זהה, וערך הגיבוב של הבנייה יתאים לזה שעובר לרשת.
- סביבות בדיקה. צומת מקומי להרצות מהירות ורשת בדיקה נפרדת לאינטגרציה, שבה בודקים מיגרציות מצב, עבודת מפתחות ותרחישים עם השהיית סופיות אמיתית.
- בדיקה לפני שחרור. מריצים בדיקות על נתיבים קריטיים בחוזה, בודקים ערכי גבול של הפקדות ומתרגלים חזרה לארטיפקט הקודם.
- פריסה מדורגת. תחילה רשימת חשבונות מוגבלת, אחר כך כולם — עם ניטור צריכת האחסון וכשלי קריאות.
- מסירה והדרכה. מוסרים תיעוד, סכימת חשבונות ותפקידים, גישות והוראות לשחרור עדכונים, כדי שהצוות ימשיך לעבוד בלעדינו.
חשבונות ואחסון ב-Near: מדיניות גישה
ב-Near הגישה נקבעת לא רק לפי קוד החוזה, אלא גם לפי היררכיית החשבונות: לכל אחד מפתח משלו, סט משלו של קריאות מורשות ונפח נתונים משלו באחסון הקבוע. לכן באספקה נכלל לא רק החוזה, אלא גם מסמכים שלפיהם ניתן לשחזר ולהעביר גישה ואחסון לצוות אחר — בלי לשחזר את הלוגיקה מהתכתבות.
- מפת חשבונות ותפקידים: בעלים, חשבון לפריסת גרסאות חדשות, חשבונות שירות לקריאות אוטומטיות ותפקידים לקריאה בלבד — הרשאות אינן מתערבבות במפתח אחד.
- מדיניות גישה: אילו מתודות זמינות לכל תפקיד, מה דורש אישור במפתח שני, מה מוגבל ברשימת כתובות או בחלון זמן.
- סכימת אחסון המצב: אילו נתונים נמצאים באחסון הקבוע, מה מחושב תוך כדי תנועה, כיצד בנויים מפתחות הרשומות וכיצד משתנה מאזן האחסון עם גידול הנפח.
- תקנון עדכון: סדר פריסת גרסה חדשה — הכנת העברת מצב, הרצה על עותק הרשת, החלפה — עם נקודות שבהן אפשר לעצור את התהליך בבטחה.
- תקנון חזרה לאחור: כיצד להחזיר גרסה קודמת יחד עם מצב תואם, מי מקבל את ההחלטה ובכמה זמן הפעולה מתבצעת.
- הפרדת סביבות: סטים נפרדים של מפתחות לרשת הבדיקה ולרשת הראשית, איסור על העברת מפתחות ונתונים ביניהן.
- יומן פעולות: אילו פעולות מתועדות, היכן נשמרים הרשומות וכיצד לנתח תקרית לפיהן בלי לבנות מחדש את החוזה.
התיעוד נדרש לא לצורך דיווח: כעבור חצי שנה מהנדס חדש נכנס לפרויקט דרכו. את כל האמור לעיל מנהלים במאגר לצד הקוד — חוזה ב-Rust ותיאורי גישה משתנים בסט שינויים אחד.
מקרה בוחן: העברת לוגיקה לחשבון חדש תוך שמירת נתונים
מה היה
בחשבון אחד חיו גם הלוגיקה וגם המצב, ושחרור גרסה כלל שלבים ידניים: לבנות את החוזה, להעלות את הקוד, להדביק את המצב ולבדוק אותו בעין. הבנייה לא חזרה על עצמה — שתי הרצות מאותם קבצי מקור הניבו ארטיפקטים שונים, והפער צף כבר בחשבון חי. לא הייתה חזרה לאחור: במקרה של שגיאה החשבון הוקם מעותק, והאי-זמינות נמשכה שעות.
מה נהיה
העברת הלוגיקה לחשבון חדש ב-Near פורקה לבנייה ניתנת לשחזור ולשלב נפרד של מיגרציית מצב. הסקריפט מחשב מפתחות וסכומי ביקורת בחשבון הישן, ואחר כך בחדש, ונעצר במקרה של אי-התאמה — מצב פגום לא יוצא לעבודה. החשבון הישן נשאר נקודת חזרה לאחור: כל עוד הבדיקות לא עברו, ההחלפה מתבטלת בפעולה אחת.
מספר השלבים הידניים ירד ל-3 במקום 12, ההעברה אורכת כחצי שעה במקום ארבע שעות. כל ההעברות עוברות ללא אי-התאמות מצב, בעוד שלפני כן כשל בערך כל ניסיון שני. החזרה לחשבון הקודם — דקות, ולא שעות של התאוששות מעותק, והיא מתבצעת באותה פקודה כמו ההעברה.
מה לעשות אם הלוגיקה כבר פרוסה ומחזיקה נתונים?
עדכון חוזה ב-Near בנוי כך: הקוד נדרס כולו, ואחסון המצב נשאר ללא שינוי. לכן פריסה חוזרת לאותו חשבון כשלעצמה לא מאפסת את הנתונים — הסיכון הוא אחר: הקוד החדש מתחיל לקרוא מפתחות ישנים לפי סכימה שהשתנתה, ונכשל בקריאה הראשונה או, גרוע מכך, מחזיר בשקט ערכים שגויים.
תאימות הסכימה נשמרת באמצעות משמעת: שדות מוסיפים לסוף המבנה, סדר וטיפוסים של קיימים לא נוגעים בהם בלי צורך, ותיקונים לא תואמים מוציאים למתודת מיגרציה נפרדת.
היא מאתחלת מחדש את החוזה תוך התעלמות מפורשת מהמצב הקודם, קוראת מפתחות ישנים, מפרקת אותם לפורמט החדש וכותבת אותם בחזרה בקריאה אחת — כדי שהמצב לא יישאר במצב ביניים בעת ניתוק.
מעבר לחשבון חדש נדרש כשהבעלים משתנה או הכתובת עצמה. אין כאן העברה אוטומטית: את המצב מעבירים בקריאת מפתחות וכתיבה לחשבון החדש, או משאירים את הישן כשכבת דקה שמעבירה קריאות הלאה.
הדרך השנייה עדיפה אם כבר מפנים לכתובת ארנקים, פרונטנד וחוזים אחרים — הקריאות שלהם ממשיכות לעבוד בלי שינויים.
כדי שהאפליקציה תישאר עובדת, שומרים על שמות וחתימות המתודות הקודמים, ואת המיגרציה מוציאים לקריאה נפרדת שמתבצעת לפני ההחלפה. חזרה מתבצעת על עותק המצב, לפני ואחרי משווים ערכי ביקורת — יתרות, מספר רשומות, זמינות מתודות ציבוריות. את הקוד הקודם מחזיקים בהישג יד לפריסת חזרה, אם הבדיקות על נתונים חיים לא יתאימו.
ספקות טכניים לפני תחילת העבודה
לפני ההתחלה כמעט כל צוות שואל את אותן שאלות: היכן יאוחסנו המפתחות, מה יקרה לחשבון כשמעדכנים קוד, כיצד להעביר גישה מסביבת בדיקה לפרודקשן והאם אפשר לסמוך על חוזה זר. להלן תשובות קצרות לכל אחת.
מבחינתנו זו לא התכתבות, אלא חלק מהעבודה: החלטות מקובעות בקונפיגורציה, ולא בהודעות צ'אט — אחרת כעבור חצי שנה איש לא יזכור למה למפתח יש רמת הרשאות כזו.
איך מפתחות גישה לא יגיעו למאגר וליומנים?
מפתחות פרטיים נשמרים מחוץ לקוד: מקומית — באחסון המערכת, בבנייה אוטומטית — במשתני סביבה מאובטחים עם גישה מוגבלת. לפריסה מונפק מפתח עם הרשאה לקרוא רק למתודות מסוימות בחוזה, ולא גישה מלאה לחשבון: דליפה של מפתח כזה לא מאפשרת למשוך כספים. לאחר מסירת הפרויקט ההרשאות מבוטלות ומונפקות חדשות.
מה יקרה לחשבון ולנתונים בעת עדכון החוזה?
הקוד מתעדכן במקום, החשבון והאחסון שלו נשמרים, ולכן פניות לכתובת הקודמת ממשיכות לעבוד. פער נוצר אם מבנה הנתונים או חתימות המתודות השתנו. אנו מתארים מראש מיגרציית מצב, מוסיפים פונקציות העברה ומריצים את העדכון בסביבת בדיקה מבודדת לפני שנוגעים בחשבון הפרודקשן.
כיצד מועברת גישה בין סביבת בדיקה לפרודקשן?
אי אפשר להעביר מצב ישירות — הסביבות בלתי תלויות. מועברת קונפיגורציה: רשימת חשבונות, סט מפתחות, סכימת הרשאות ונתוני אתחול, והמצב נפרס מחדש באמצעות אותן מיגרציות. כך הפרודקשן חוזר על תרחיש הבדיקה המאומת, ולא מעתיק אותו באופן עיוור.
האם אפשר לסמוך על חוזה שכבר נכתב — שלנו או זר?
לפני שיפור קוד זר אנו משווים את הבייט-קוד שפורסם לקוד המקור ולהרכב התלויות: אם הם אינם תואמים, מסוכן לשנות את הלוגיקה. בהמשך — בדיקת הרשאות מפתחות, נקודות עדכון ולוגיקת משיכת כספים. פערים שנמצאים מתעדים כתנאי שיש להסיר לפני תחילת העבודה.
נדון במשימה: נחזור עם הערכה ותוכנית
כדי לחזור עם הערכה ותוכנית עבודה, ולא עם ניסוחים כלליים, מספיק לנו סט מינימלי של נתוני פתיחה. ככל שהקלט קונקרטי יותר, כך לוחות הזמנים מדויקים יותר ופחות סבבי הבהרות לפני תחילת העבודה.
מה לשלוח להתחלה:
- קישור למאגר או ארכיון עם קוד המקור של החוזה ב-Rust, כולל מניפסט הבנייה וגרסת המהדר המקובעת.
- רשימת חשבונות וייעודם: איזה חוזה נפרס לאן, מי הבעלים, אילו מפתחות גישה הונפקו ולאילו מתודות.
- תיאור אחסון: אילו מבנים נכתבים למצב, הנפח הצפוי, האם יש מיגרציות וכיצד מתוכננת העברת הנתונים.
- רשת יעד ומצב עבודה: בדיקה או ראשית, תפוקה נדרשת, מגבלות כתיבה.
- סכימת הפריסה הנוכחית: סקריפטי בנייה, שלבים ידניים, מה כבר אוטומטי ומה נעשה ידנית.
- דרישות לבדיקות: אילו תרחישים חייבים לעבור לפני שחרור ומי מאשר את המוכנות.
ננתח את החוזה, מודל המצב והרשאות המפתחות בנפרד — בפריסה אלו שלושה מקורות כשל בלתי תלויים. נראה היכן מקודדות הנחות לגבי גודל המצב, כיצד מתנהגת הלוגיקה כששינויים מיושמים חלקית ומה קורה לחשבון בפריסה כושלת.
נחזור עם הערכה ותוכנית עבודה: שלבים, סדר הפריסה, נקודות חזרה למצב הקודם, הרכב הבדיקות ומה שיידרש מצדכם בכל שלב. תארו את המשימה — נשלח ניתוח עם לוחות זמנים קונקרטיים.







