דלגו לתוכן

אירועי תחום

אירועי תחום הם מנגנון הניתוק שמאפשר לתכונות לתקשר בלי תלויות ישירות. במקום שתכונה א’ תקרא לתכונה ב’, תכונה א’ מפרסמת אירוע ותכונה ב’ נרשמת אליו.

ה-DomainEventBus הוא אפיק פרסום/מינוי לשידור בתוך התהליך. המפרסמים קוראים ל-publish(event); המנויים צורכים זרם on<T>() טיפוסי. כל אירוע מממש DomainEvent ונושא occurredAt.

האפיק פועל בתוך cc_server. כל מפרסם וכל מנוי פעיל יושבים שם. שום לקוח אינו רואה את האפיק הזה. מה שלקוח רואה הוא תת־קבוצה נבחרת שהשרת משדר מחדש כמסגרות notifications/* ב־JSON-RPC.

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

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

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

כדאי לדייק בנקודה אחת שהאפיק אינו הבעלים שלה.

יומן הביקורת אינו היטל של זרם האירועים. כל פעולת RPC משנה מבוקרת כברירת מחדל — RepoOp.audited הוא true כברירת מחדל, ופעולה יוצאת מכך רק בהצהרה מפורשת audited: false, מעשה מכוון שנראה על הפעולה עצמה. המשגר מוסיף את השורה “מי עשה מה, ומאיפה” מיד אחרי קריאה מוצלחת. אין DomainEventAuditBridge. ActivityLogPersister כותב שורות activity_log מאירועי ActivityLogged; זהו פיד נפרד מביקורת ה-RPC.

אפיק האירועים כן מהווה את התעבורה עבור התראות ועבור אוטומציה. הוא אינו מערכת הרישום הקובעת.

  • התראות. עשרים ואחת מחלקות אירועים נהפכות על ידי השרת למסגרות תעבורה notifications/*, נרשמות לפיד עמיד לכל סביבת עבודה ומשודרות לסשנים מחוברים. מסגרת שה-workspace_id שלה מציין סביבת עבודה שהמשתמש של הסשן אינו חבר בה נזרקת בשרת; הלקוח מסנן את השאר לסביבת העבודה שהוא מביט בה.
  • אוטומציה מונעת אירועים. טריגרים של פייפליין נרשמים לאפיק ומתחילים אוטומטית פייפליינים תואמים (ראו בהמשך).
  • תגובות מחזור חיים. יצירת סביבת עבודה זורעת את סוכן ה-CEO וסוכני המומחים שלה, את תבניות הפייפליין המובנות ואת חבילות ההערכה ההתחלתיות. הרצת סוכן שהושלמה מחדשת שלב פייפליין מושהה, סוגרת משימה, מזינה את מפקח היעדים, יכולה להעיר בודק מסוים בשמו, ויכולה להפעיל מחדש מוביל צוות. בקשת משיכה שמוזגה או מרחב שנמחק מפעילים איסוף אשפה של עצי עבודה.
  • סנכרון בין ספקים. שינויים מקומיים בכרטיסים נדחפים אל הספקים המוגדרים בידי מתאם שמאזין לחמישה אירועי כרטיסים.

האירועים חולשים על כל משטח המוצר. ברמה גבוהה:

  • סביבות עבודה, סוכנים ומאגרים — יצירת סביבת עבודה, השלמת הרצה, רישום מאגר, עדכוני מיומנויות
  • בקשות משיכה — פרסום, שינויי סטטוס, מיזוגים, בקשות סקירה, אזכורים, מעקב אחר בקשות משיכה שיצרתם, בקשות משיכה שזוהו מבחוץ
  • הודעות — הודעות, מרחבים והתקדמות הקצאת מרחב
  • כרטיסים — יצירה, הקצאה, הקצאה מחדש, פרטים, סטטוס ושלוש התוצאות הסופיות
  • משימות — מסגרות מחזור חיים ממוספרות לרצף עבור הרצה נשלחת אחת, כדי שלקוחות יוכלו לסדר אותן ולהסיר כפילויות
  • פייפליינים — אירועי הרצה סופיים בלבד (הושלמה, בוטלה, נכשלה)
  • נצפות — רשומות יומן פעילות וספי תקציב
  • זהות וחברות — חבר נוסף, הוסר, התפקיד שונה
  • לוח שנה ופגישות — פקיעת תוקף ההרשאה, התחלת פגישות וסיום הקלטות
  • תחנות — השתלטות, פינוי וסגירה בלתי צפויה

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

לקטלוג המלא — כל 53 מחלקות האירועים הקונקרטיות, המטענים שלהן ו-24 המנויים שצורכים אותן — ראו עזר אירועי תחום. הדף ההוא הוא המלאי; הדף הזה הוא המודל.

בקרת גישה חיה נשענת על שני מנגנונים שונים

קטע בשם “בקרת גישה חיה נשענת על שני מנגנונים שונים”

אירועי חברות ומכשירים נראים סימטריים ואינם כאלה, וזה חשוב אם אתם מנתחים באיזו מהירות שלילה נכנסת לתוקף.

שלילת מכשיר אכן מסיימת את הסשנים שלו. השרת צופה בטבלת המכשירים המשויכים ומפיל כל סשן חי שהמכשיר שלו יצא מהסט הפעיל, בתוך שניות.

הסרת חבר אינה סוגרת את השקע. WorkspaceMemberRemoved נצרך: LocalRpcServer ו-RemoteRelayHost מפילים את המינויים של אותו משתמש לסביבות העבודה שאליהן הוא מחובר, ו-RemoteEventForwarder מבטל את מטמון החברות שלו כך שמסגרות נוספות לאותה סביבת עבודה אינן נדחפות. מה שמסרב ל-RPC הבא הוא עדיין שער התפקיד, שפותר מחדש את החברות בכל קריאה — כך שהבקשה הבאה שלהם נדחית עם “Not a member of this workspace”. ההשפעה מיידית לכל מה שהם ינסו לעשות; היא רק אינה מושגת על ידי ניתוק הקשר איתם.

טריגרים של פייפליין נרשמים לאירועי תחום ומתחילים אוטומטית פייפליינים תואמים. PipelineTriggerDispatcher מאזין לאפיק כולו, ואז:

  1. עוצר מיד, אלא אם סוג האירוע הוא כזה שהוא יודע למפות למטען
  2. מאתר טריגרים מופעלים שתואמים את סוג האירוע הזה, בכל סביבת עבודה
  3. מסנן כל אחד לסביבת העבודה שלו ומיישם את מסנן התאמת המטען שלו
  4. מפעיל הרצה לכל טריגר ששורד

האילוץ החשוב הוא שלב 1. האפיק נושא 53 סוגי אירועים; בורר הוספת הטריגר מפעיל הרצה עבור ארבעה עשר אלה (ענפי המטען של EventPayloadMapper): ExternalPrDetected, PullRequestPublished, PullRequestStatusChanged, PrMerged, MessageReceived, TicketAssigned, TicketCompleted, TicketFailed, TicketCancelled, BudgetThresholdCrossed, RepoAdded, MeetingRecordingStopped, SkillUpdated ו-SpaceDeleted. שום דבר אחר אינו יכול להפעיל פייפליין.

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

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