asp.net - אי המתנה לפונקציה

מענדי

New member
asp.net - אי המתנה לפונקציה

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

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

האם יש אופציה לשגר-ושכח לפונקציה, ולמנוע מהמשתמש את זמן ההמתנה לסיום ריצת הפונקציה?
 

Royi Namir

New member
-

יותר מומלץ :
אתה כותב ל DB ( או לכל מנגון אגירה אחר חיצוני) את כל המיילים שאומרים להישלח ( כלומר כל הפרמטרים וכו)
ואז תבנה JOB שפשוט ישלח את המיילים ( אם מוגדר לך MAIL AGENT ב SQL)
או שפשוט יהיה קובץ חיצוני ( הרצה) EXE או SERVICE שפשוט דוגם את ה QUEUE ב DB ( את הטבלת של האימיילים , עבור כל אלה שעוד לא נשלחו) ופשוט שולח אותם.


פתרונות אחרים כאן :
http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html
 

מענדי

New member
נחזור לשולחן השירטוטים

זאת מערכת ביצור, ועד היום הפונקציה עבדה טוב ומהר.
&nbsp
וכרגיל במערכות כאלו מישהו היכן שהוא החליט שחייבים לסבך את הפונקציה, ולהוסיף לה איתור נמענים בזמן אמת ועוד - וזה האריך את זמן הריצה.
&nbsp
מהפוסט של סטפן אני מבין שפיתרונות שגר ושכח לא מומלצים בasp.net מסיבות שונות.
&nbsp
נאפיין פיתרון של Queue או DB - ונקווה שהלקוח יבין שהוא גם צריך לשלם על זה

&nbsp
&nbsp
 

Royi Namir

New member
כן

הם לא מומלצים מהסיבה של RECYCLE שיכול להעיף את העבודה שלך
ולכן יש את האופציה השלישית שכן מאפשרת את זה ( ויש גם ספריות בנושא)

אבל עזוב
הכי נכון זה שמישהו אחר שהתפקיד שלו זה לקרוא מה QUEUE - אימיילים , לשלוח אותם
ןזה יכול להיות CMD או SERVICE או כל ישום אחר
וכמובן שה QUEUE יכול להיות כל מנגנון אחסון. לשם ההפשטה בחרתי בתשובתי להגיד SQL SERVER ( גם בגלל הסיבה שיש לו JOBS ובכלל אופציה הגדרת שרת MAILS)
אבל אם תשאל אותי - SQL SERVER לא אמור לשלוח מיילים
למרות שאני רואה א זה הרבה אבל אני לא מסכים עם זה
SQL SERVER זה מסד נתונים ומסד נצונים צריך להחזיק נתונים
את הנתונים של שליחת אימייל - שמישהו אחר יקרא ויעשה.
 

nocgod

New member
לדעתי

כדי לא להמתין אפשר להריץ Task שלא מחכים לו (לא עושים לו await או result) זה הדרך המלוכלכת.

הדרך היותר יפה זה להבין שיש לך פה 2 משימות שלא קשורות אחת לשניה:
1. שמירת המידע ב DB
2. שליחת המיילים לנמענים

אז מה עושים? separation of concerns
האתר (בין אם זה MVC או webApi) מקבל את הבקשה מהלקוח, מעדכן את הבסיסי נתונים וכל הדברים שבאחריותו. ברגע שהשלב הזה הסתיים אתה מוסיף הודעה לאיזשהו queue, כזה שהמאזין יכול לעשות עליו block או לקבל הודעה על זה שנכנס לqueue הזה איזשהו פריט. לדוגמא rabbitmq, azure storage queue+webjobs/functions וכד'.
כאשר הצרכן של התור הזה קורא את ההודעה הוא יאסוף את כל המידע של המיילים וישלח אותם.

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

Royi Namir

New member
אם ה IIS רוצה לעשות RECYCLE

(בהנחה שאתה תחת IIS) - הוא ממש לא יתחשב ב TASK שלך
אז לא הייתי הולך על זה.
לגבי ה QUEUE , בהחלט שכן הייתי הולך על זה ( וגם המלצתי על זה)
 

nocgod

New member
קראתי לזה הדרך המהירה והמלוכלכת והדרך השניה עדיפה עלי

אם לא היה ברור - אני לא ממליץ לעשות fire-and-forget tasks בקונטקסט הנוכחי!
פיתרון שמחלק את המשימות הוא הנכון יותר והעדיף יותר מבחינת ארכיטקטורה.
 

Royi Namir

New member
לא רוצה להיות nitpick אבל כתבת "הדרך היותר יפה"

זה לא קשור למלוכלך או יפה
יש מצב שמה שהוא כותב בכלל לא יעבוד
אז זה קשור לזה שאם זה חשוב לו שהעבודה תתבצע ב 100% אז הוא לא אמור בכלל ללכת לכיוון הזה.

בכל מקרה אני ואתה מכוונים לאותו כיוון :)
 

מענדי

New member
זו מערכת ותיקה בASP.NET FORM.

&nbsp
נכון לעכשיו ירדנו מהTASK - מכיון שהפונקציה משתמשת במשאבים שמשתחררים בסוף ריצת הדף (DB Connection ואובייקטים שונים) - ולשנות את הפונקציה יעלה לא פחות ממעבר לתור ושליחת מייל מתהליך חיצוני.
&nbsp
&nbsp
 
למעלה