כל קריאה שילמה על מעקב שינויים
רוב נקודות הקצה רק קוראות נתונים, אבל EF Core עקב אחרי כל ישות שנטענה.
הגדרתי no-tracking כברירת מחדל לכל ה־context, ומעקב מופעל במפורש רק במסלולי העדכון. בנוסף הוסרו מהשאילתה של הפוסטים includes שלא היה בהם צורך.
הובלתי את הבנייה מחדש של אפליקציית עזרה הדדית עבור מפעיל ישראלי של קהילת עזרה. משתמשים מפרסמים בקשה (הסעה לבית חולים, כלב שאבד, כיסא גלגלים לשבוע), ושכנים בסביבה שבחרו לקבל התראות מקבלים אותה ועונים בצ׳אט, בוואטסאפ, ב־SMS או בשיחה. הגרסה החדשה החליפה אפליקציה ותיקה באותם דפי חנות, שמרה על כל המשתמשים והנתונים, ומחליטה בשאילתה אחת למסד הנתונים מי צריך לשמוע על כל בקשה.
למפעיל כבר הייתה אפליקציה עם משתמשים אמיתיים ושנים של בקשות במסד MySQL. היה קשה להרחיב אותה: לא היו בה קבוצות, צ׳אט בתוך האפליקציה או הגדרות התראה אישיות, ולכן אפשר היה לצמצם את ההתראות רק באופן גס. המשימה הייתה לבנות מחדש את השרת ואת האפליקציה בלי לאבד אף משתמש, ולתת לכל אחד לבחור בדיוק אילו בקשות יעירו לו את הטלפון: אילו קטגוריות, אילו מילות מפתח, באיזה מרחק, מאילו ערים ובאילו שעות.
התרשים רחב מהמסך: החליקו הצידה לצפייה בכולו →
האפליקציה מדברת גם ישירות עם שירות הצ׳אט דרך ה־SDK שלו, עם טוקן משתמש שה־API מנפיק. תמונות נשמרות באחסון אובייקטים, וב־SQL נשמרות רק הכתובות שלהן. ההתחברות היא במספר טלפון וקוד SMS חד־פעמי. משתמש חסום מקבל מהשרת קוד סטטוס ייעודי, והאפליקציה מעבירה אותו למסך ”הגישה נחסמה”.
כללי הקטגוריה, מילת המפתח, המרחק והעיר מתורגמים לשאילתת LINQ אחת. המרחק מחושב בפונקציית Haversine ב־SQL שממופה ל־EF Core, והרדיוס האפקטיבי הוא הקטן מבין הטווח שהמשתמש בחר והרדיוס של הבקשה. אף רשימת משתמשים לא נטענת לזיכרון רק כדי לזרוק את רובה. המחיר: פונקציית מרחק סקלרית לא משתמשת באינדקס, וזה בסדר בהיקף הנוכחי. אם בסיס המשתמשים יגדל מאוד, הצעד הבא הוא אינדקס מרחבי.
כל משתמש שמתאים מקבל שורה בתיבת ההתראות, גם בלי טוקן מכשיר תקין, כך ששום דבר לא הולך לאיבוד אחרי התקנה מחדש או הפעלה מחדש של ההתראות. פוש נשלח רק למי שלא נמצא בשעות השקט שלו, ושעות השקט יכולות לחצות חצות (22:00–06:00). המחיר: יותר שורות בטבלת ההתראות, ולכן התיבה מוצגת בדפים של 10.
יצירת בקשה שומרת אותה ומכניסה אותה לתור. worker ברקע בוחר את קהל היעד, כותב לתיבה ושולח בקשת פוש מקובצת אחת. מי שמפרסם לא מחכה למאות טלפונים. המחיר: התור רץ בתוך התהליך, ופריטים שממתינים בזמן restart יכולים ללכת לאיבוד. תהליך worker נפרד כבר הוקם כשלד, כדי להוציא את התור החוצה.
במקום להרחיב את אפליקציית ה־MySQL הישנה, הנתונים עברו בהעתקה מרוכזת (bulk copy) למסד staging. משם סקריפט T-SQL עם מתג @DRY_RUN, בדיקות הגנה וטיפול בכפילויות העביר אותם לסכמה החדשה. האפליקציה החדשה שוחררה תחת זהויות החנות הישנות, כך שמכשירים קיימים פשוט קיבלו עדכון. המחיר: סכמה נוספת וכלי חד־פעמי שצריך לתחזק עד המעבר.
מתוך היסטוריית הקומיטים של שני המאגרים. מבחר:
רוב נקודות הקצה רק קוראות נתונים, אבל EF Core עקב אחרי כל ישות שנטענה.
הגדרתי no-tracking כברירת מחדל לכל ה־context, ומעקב מופעל במפורש רק במסלולי העדכון. בנוסף הוסרו מהשאילתה של הפוסטים includes שלא היה בהם צורך.
במסד הישן היו בקשות עם זמנים חופשיים, דיווחים כפולים, טבלת מיקומים נפרדת, ומשתמשים שזוהו רק לפי מספר טלפון.
בניתי הסבה בשני שלבים: העתקה מרוכזת מ־MySQL לסכמת staging, ואחריה מיפוי ב־T-SQL עם זמנים שמוגנים מגלישה, איחוד דיווחים כפולים, THROW כשחסרים נתוני ייחוס, ומצב הרצת ניסיון שמדווח ספירות ועושה rollback.
בגרסה הראשונה ההתראות נשלחו בתוך קריאת יצירת הפוסט, כך שהפרסום האט ככל שקהל היעד גדל.
ביטלנו את השליחה בתוך הקריאה והוספתי תור עם worker ברקע. טוקן המכשיר מתעדכן בכל התחברות, ורק משתמשים עם טוקן תקין מקבלים פוש.
פוסטים בקבוצות פרטיות יכלו להופיע בפיד של אנשים שלא היו חברים בהן.
הפיד וההתראות מסוננים לפי חברות בקבוצה, נוספה אפשרות מפורשת ל”פוסט ציבורי בקבוצה”, ובבדיקת אבטחה בפברואר 2026 נסגרו פערי גישה נוספים ב־API של הפוסטים.
סינון המיקום ושעות השקט לא תאם את מה שהמשתמשים הגדירו, והרדיוס של הבקשה עצמה לא נלקח בחשבון.
הרדיוס האפקטיבי הוא עכשיו min(reader range, request radius), ובדיקת שעות השקט מטפלת בטווחים שחוצים חצות.
ההתאמה הסתמכה על המיקום ששמור בפרופיל, והוא מתיישן אצל מי שזז הרבה.
האפליקציה שולחת את המיקום הנוכחי בפתיחה וכל 5 דקות, ולא מרעננת את הפיד כשהמיקום לא השתנה. משתמשים יכולים גם לעקוב אחרי כמה ערים.
עברית וערבית הן שפות מלאות באפליקציה, אבל חלק מרכיבי צד שלישי התעלמו מכיוון התצוגה (הסליידר, ההשלמה האוטומטית של מקומות, כותרת הצ׳אט ב־iOS).
כפינו את הכיוון דרך שכבת ה־i18n, תיקנתי את רכיב המקומות עם patch-package, שדרגנו את ספריית הסליידר, ועברנו על יישור ה־RTL מסך אחרי מסך.
כשכמה בקשות נכשלו יחד בגלל טוקן שפג, כל אחת ניסתה לרענן אותו בעצמה, ומשתמשים חסומים יכלו להיתקע במסך טעינה.
ה־interceptor של Axios משתף עכשיו רענון אחד פעיל בין כל הקוראים. משתמש חסום מקבל קוד סטטוס ייעודי שמעביר אותו למסך ”הגישה נחסמה”.
שחרור כדף חנות חדש היה מחייב לבקש מכל משתמש קיים להתקין מחדש.
הקונפיגורציה של iOS ו־Android עברה לזהויות החבילה הקיימות של האפליקציה הוותיקה, וקודי הגרסה יושרו, כך שהחנויות מקבלות אותה כעדכון.
הדמיה קטנה של כללי ההתאמה עם שישה שכנים בדויים. אין כאן קוד או נתונים של הלקוח. שנו את הבקשה וראו מי מקבל אותה לתיבה, מי מקבל פוש, ולמה האחרים לא.
שיחת אבחון חינם · 30 דקות · ללא התחייבות
כתבו בכמה שורות: איזה תהליך או מערכת, מה כואב היום (זמן, טעויות, עלויות או פיילוט AI שנתקע) ומי עובד עם זה. אחרי שיחה קצרה מקבלים תוך כ־3 ימים תוכנית כתובה והצעת מחיר סגורה.
נפתח מייל מוכן מראש · מענה תוך יום עסקים
ה־AI קורא. הקוד סופר.
כל הפרויקטים