מחלקת "תכנות נורמלי במערכות 'ימות'..."
-
אולי אם מישהו מבין איך אסטריסק ARI עובד,
אפשר לשכפל את זה גם לכאן.
https://github.com/asterisk/node-ari-clientהרעיון הוא, שכל אירוע שקורה במערכת, נשלח ע"ג ווב-סוקט ללקוח ה-ARI,
ואופן שליחת הפקודות למערכת, הוא HTTP.והשלוחות כתובות כקטע קוד רציף, בעוד שכל משתמשי המערכת מגיעים ביחד.
זה אומר, שיש איזה מנגנון שדואג שכל קריאה של לקוח תגיע למקום שהוא היה קודם, וממשיך משם.על אסטריסק-ארי: https://wiki.asterisk.org/wiki/display/AST/Introduction+to+ARI+and+Channels
-
- עדיין לא הבנתי איך אתה מקשר בין הקריאה החדשה לתהליך שמחכה ואיך הוא ידע איפה לעצור ואיפה להמשיך
בPHP אתה יכול לעצור את התהליך עם תנאי שלא ימשיך הלאה כל עוד התנאי לא התקיים
אבל כאן נראה לי שאתה רוצה לחסוך את השימוש בתנאי - כפי הידוע לי ימות שולחים בקשה עם curl או משהו מקביל ופשוט כל פעם מוסיפים עוד ערך לסטרינג
לכן לא נראה לי ששייך לעשות כאן ווב-סוקט כמו באסטריסק
למשל בAGI אם אני שולח שתי פקודות א-סינכרוניות להקראת קובץ מסויים בהפרש של 2 שניות
המערכת מתחילה להקריא את הקובץ הראשון למשך 2 שניות ואז מפסיק ועובר לקובץ השני
וזה לא אפשרי כמובן בימות המשיח
אמנם אם ימות היו פותחים את האפשרות של fastagi זה היה פתר לך את כל הבעיות וזה היה נותן אפשרות לכתוב כמו אסטריסק רגיל
והיית מרוויח כמעט את כל המעלות של אסטריסק בלי להעמיס על השרת שלך
אבל כנראה ימות לא יעשו את זה כל כך מהר
א. כי זה יכול ליצור להם הרבה חורים באבטחה שהם לא חשבו עליהם
ב. כנאה שזה יעמיס להם על השרתים יותר מאשר קריאות HTTP רגילות - עדיין לא הבנתי איך אתה מקשר בין הקריאה החדשה לתהליך שמחכה ואיך הוא ידע איפה לעצור ואיפה להמשיך
-
@nigun לא התכוונתי לעשות ווב-סוקט...
רק שאם שם יש אופציה של קטע קוד שמבוצע בהתאמה לכמה קריאות (שם - ווב-סוקט, כאן - בקשות HTTP), אז זה בדיוק מה שרציתי.התחיל להתבשל לי רעיון,
ליצור אינטרפייס לכל מזהה, לשים את כולם במערך,
ואז - אם המזהה שולח בקשה פעם שנייה, פשוט להפעיל איזה קולבק באינטרפייס הספיציפי שלו.ואז אפשר לכתוב קוד שכולו מבוסס קולבקים (מושג שלמדתי לפני יומיים...), ולכל אינטרפייס זה ירוץ בנפרד.
זה עדיין בוסר, ואת נוד אני מכיר מאתמול.
אז אם מישהו שמכיר את נוד טיפה יותר יעזור לפתח את זה, אני אשמח. -
@MusiCode אמר ב[מחלקת "תכנות נורמלי במערכות
זה נראה ככה:
בקשה ראשונה: https://call2yemot.com/ext
התשובה: read=f-000=ivr,n,...
(המילה הראשונה read היא מסמנת קבלת הקשות. אח"כ, שם הקובץ שיושמע כתפריט. אח"כ שם המשתנה שיוחזר)למעשה הבקשה הראשונה נראית כך:
https://call2yemot.com/ext?ApiPhone=0504100000&ApiCallId=b6t76r7v6v4754c
-
@MusiCode מה שאתה צריך הוא מימוש של generator
coroutines.משהו כזה:
var activeCalls = {}; function router(req, res) { var callId = getCallId(req); var currentCall = activeCalls[callId]; if (currentCall) { var returnedValue = extractValue(req); } else { currentCall = activeCalls[callId] = Call(); returnedValue = null; } var reply = currentCall.next(returnedValue); return res.send(reply.value); } function* Call() { yield playfile("file"); var f = yield read("file", 1, 5, ...); yield goToFolder("/7/" + f); yield hangup(); }
אני לא מצרף מימוש של playfile, read, gotofolder, hangup כי אין לי מושג איך ה-API של ימות עובד. אבל כל אחד מפונקצייות אלו אמור להחזיר את המחרוזת שצריך להשיב למערכת ימות
-
בהמשך להנ"ל,
בינתיים השתמשתי רק בקוד סינכרוני בתוך פונקצייתcall
. אבל בחיים האמתיים תצטרכו מן הסתם קוד איסינכרוני.
מאז נוד 10 ומעלה אפשר להשתמש ב-Asynchronous generators.
זה נראה כך,var activeCalls = {}; async function router(req, res) { var callId = getCallId(req); var currentCall = activeCalls[callId]; if (currentCall) { var returnedValue = extractValue(req); } else { currentCall = activeCalls[callId] = Call(); returnedValue = null; } var reply = await currentCall.next(returnedValue); return res.send(reply.value); } async function* Call() { yield playfile("file"); var f = yield read("file", 1, 5, ...); yield goToFolder("/7/" + f); yield hangup(); }
אני מקווה ללמוד יותר את ה-API של ימות ואז אוכל להביא משהו יותר מושלם.
-
@yossiz אמר במחלקת "תכנות נורמלי במערכות 'ימות'...":
אני ממש ממש לא מכיר את מערכת ימות
אתה לא מפסיד כלום
בכל מקרה מעבר לשלוחה אחרת בPHP יראה משהו כזהprint "go_to_folder=../";
ואם אתה רוצה שישמע הודעה לפני המעבר
print "id_list_message=f-028.n-100.f-029&go_to_folder=/4&";
שזה בעצם משמיע לו את קובץ 028 ואז את המספר 100 ואז את קובץ 029 ואז עובר לשלוחה 4
-
@nigun אמר במחלקת "תכנות נורמלי במערכות 'ימות'...":
print "go_to_folder=../";
ואז בממשק של ימות מגדירים את השלוחה שינתק?
אגב, לא הבנתי מה בדיוק רצית לעשות בקוד ה-GO שהבאת למעלה, אבל מימוש של coroutine הוא אפילו יותר טבעי ב-GO מאשר ב-JS. לכאורה אפשר לעשות מחלקה שעושה את השימוש בימות ממש טבעי וזורם.
-
@yossiz אמר במחלקת "תכנות נורמלי במערכות 'ימות'...":
@nigun אמר במחלקת "תכנות נורמלי במערכות 'ימות'...":
print "go_to_folder=../";
ואז בממשק של ימות מגדירים את השלוחה שינתק?
כן
אגב, לא הבנתי מה בדיוק רצית לעשות בקוד ה-GO שהבאת למעלה, אבל מימוש של coroutine הוא אפילו יותר טבעי ב-GO מאשר ב-JS. לכאורה אפשר לעשות מחלקה שעושה את השימוש בימות ממש טבעי וזורם.
בקוד למעלה
ניסיתי לשאול האם אפשר להרוג תהליך שכבר רץ מקריאה קודמת
אז לצורך הדוגמה בניתי שרת HTTP שקריאה לlocalhost:8000/run מפעילה את הפונקציה run(foo)
(אין ל פונקציה כזאת כרגע זה כדי לתת הדגמה של הפעלת תהליך)
וכיון שזה קריאה א-סינכרונית אני לא צריך להישאר בדף כדי שפונקציה תמשיך לרוץ
אבל אם הפונקציה היא אינסופית או שרצה להרבה זמן
אני רוצה דרך לשלוט עליה עם קריאה נפרדת
למשל להרוג את התהליך אחרי שעה
אז רציתי שיהיה אופציה בסגנון של קריאה ל localhost:8000/kill
שמפעילה את הפונקציה kill(foo)
ובעברית "להרוג את תהליך foo"
אבל הבעיה היא שאי אפשר להשפיע על התהליך מהקריאה הקודמת ע"י קריאה בשם של התהליך (foo)
אמנם אם אני מקבל בשעת ההפעלה את הPID של התהליך אז אני יכול להרוג אותו ע"י קריאה לPID
(לכאורה אני יכול להחליט בהפעלה מה הPID כדי שאני אוכל לגשת אליו אחר כך
ואם לא אפשר לקבל אותו בהפעלה ולשמור אותו איפה שהוא
אבל כל זה נוגע להריגת התהליך אבל להמשיך הפעלה לאותו תהליך זה כבר משהו אחר -
@yossiz אמר במחלקת "תכנות נורמלי במערכות 'ימות'...":
@MusiCode מה שאתה צריך הוא מימוש של coroutines.
משהו כזה:
var activeCalls = {}; function router(req, res) { var callId = getCallId(req); var currentCall = activeCalls[callId]; if (currentCall) { var returnedValue = extractValue(req); } else { currentCall = activeCalls[callId] = Call(); returnedValue = null; } var reply = currentCall.next(returnedValue); return res.send(reply.value); } function* Call() { yield playfile("file"); var f = yield read("file", 1, 5, ...); yield goToFolder("/7/" + f); yield hangup(); }
אני לא מצרף מימוש של playfile, read, gotofolder, hangup כי אין לי מושג איך ה-API של ימות עובד. אבל כל אחד מפונקצייות אלו אמור להחזיר את המחרוזת שצריך להשיב למערכת ימות
אם זה אמיתי, זה מדהים!...
לא הבנתי, מה זה קורוטין?
אפשר הסבר?אני מנסה להבין את הקוד, אבל כמו שאמרתי,
אני בנוד מלפני כמה ימים...
יש לי נוד אחרון.
צריך איזו חבילה לזה? -
@MusiCode אמר במחלקת "תכנות נורמלי במערכות 'ימות'...":
לא הבנתי, מה זה קורוטין?
אפשר הסבר?generator
coroutineהוא בדיוק החלום שלך, זה פונקציה שמפסיקה את עצמה באמצע ומחזירה ערך, ואח"כ אפשר להמשיך אותה בדיוק מהמקום שבו היא עצרה.
אפשר לקבל ערך מהפונקציה על כל עצירה, ולהעביר לפונקציה ערך על כל המשך הרצה.ב-JS, עושים פונקציה כזאת עם התחביר:
function*
העצירה והחזרת ערך מתבצעת על ידי מילת המפתחyield
.
הרצת הפונקציה לא באמת מריצה אותה אלא מייצרת אובייקט מסוגgenerator
. אפשר לקרואgenerator.next
כדי להריץ את השלב הבא של הפונקציה.generator.next
מחזירה אובייקט בעלת 2 חברים{value: xxx, done: true/false}
.טוב, אידך פירושא זיל גמור...
אני מנסה להבין את הקוד, אבל כמו שאמרתי,
אני בנוד מלפני כמה ימים...
לאט לאט...
אבל אתה לא חייב JS כיcoroutinegenerators קיימים בהרבה שפות (לפעמים תמיכה מפורשת ולפעמים על ידי קונצים).
הדבר קיים גם בפייתון, אם כי לפום ריהטא נראה שזה קצת יותר מסובך למימושצריך איזו חבילה לזה?
לא
בעזה"י אעלה עוד מעט דוגמת hello world שעובד.