עבודות שרשור

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

כדי ליצור שרשרת של עבודות, אפשר להשתמש ב-WorkManager.beginWith(OneTimeWorkRequest) או ב-WorkManager.beginWith(List<OneTimeWorkRequest>), שכל אחד מהם מחזיר מופע של WorkContinuation.

אחר כך אפשר להשתמש ב-WorkContinuation כדי להוסיף מכונות OneTimeWorkRequest תלויות באמצעות then(OneTimeWorkRequest) או then(List<OneTimeWorkRequest>).

כל הפעלה של WorkContinuation.then(...) מחזירה מופע חדש של WorkContinuation. אם מוסיפים List של OneTimeWorkRequest מופעים, יכול להיות שהבקשות האלה יפעלו במקביל.

לבסוף, אפשר להשתמש ב-WorkContinuation.enqueue() כדי enqueue() את שרשרת ה-WorkContinuation.

בואו נראה דוגמה. בדוגמה הזו, 3 משימות שונות של Worker מוגדרות להפעלה (אולי במקביל). התוצאות של ה-Workers האלה משולבות ומועברות למשימת Worker לשמירה במטמון. בסופו של דבר, הפלט של המשימה הזו מועבר ל-Worker של העלאה, שמעלה את התוצאות לשרת מרוחק.

Kotlin

WorkManager.getInstance(myContext)
   // Candidates to run in parallel
   .beginWith(listOf(plantName1, plantName2, plantName3))
   // Dependent work (only runs after all previous work in chain)
   .then(cache)
   .then(upload)
   // Call enqueue to kick things off
   .enqueue()

Java

WorkManager.getInstance(myContext)
   // Candidates to run in parallel
   .beginWith(Arrays.asList(plantName1, plantName2, plantName3))
   // Dependent work (only runs after all previous work in chain)
   .then(cache)
   .then(upload)
   // Call enqueue to kick things off
   .enqueue();

מיזוגים של קלט

כשמשרשרים מכונות של OneTimeWorkRequest, הפלט של בקשות העבודה של ההורה מועבר כקלט לילדים. לכן בדוגמה שלמעלה, הפלט של plantName1,‏ plantName2 ו-plantName3 יועבר כקלט לבקשה cache.

כדי לנהל קלט מכמה בקשות עבודה הורה, WorkManager משתמש ב-InputMerger.

יש שני סוגים שונים של InputMerger ש-WorkManager מספק:

  • OverwritingInputMerger מנסה להוסיף את כל המפתחות מכל הקלטים לפלט. במקרה של התנגשויות, המפתחות שהוגדרו קודם יוחלפו.

  • ArrayCreatingInputMerger מנסה למזג את נתוני הקלט ויוצרת מערכים לפי הצורך.

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

OverwritingInputMerger

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

לדוגמה, אם לכל אחד מהקלט של המפעל יש מפתח שתואם לשמות המשתנים המתאימים ("plantName1",‏ "plantName2" ו-"plantName3"), הנתונים שיועברו ל-worker של cache יכללו שלושה צמדים של מפתח/ערך.

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

אם יש התנגשות, ה-worker האחרון שמסיים "מנצח", והערך שלו מועבר אל cache.

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

בקשות העבודה פועלות במקביל, ולכן אין ערובה לסדר שבו הן פועלות. בדוגמה שלמעלה, הערך של plantName1 יכול להיות "tulip" או "elm", בהתאם לערך שנכתב אחרון. אם יש סיכוי להתנגשות בין מפתחות וצריך לשמור את כל נתוני הפלט במיזוג, יכול להיות ש-ArrayCreatingInputMerger היא אפשרות טובה יותר.

ArrayCreatingInputMerger

בדוגמה שלמעלה, בהנחה שאנחנו רוצים לשמור את הפלט מכל ה-Workers של שמות הצמחים, אנחנו צריכים להשתמש ב-ArrayCreatingInputMerger.

Kotlin

val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>()
   .setInputMerger(ArrayCreatingInputMerger::class)
   .setConstraints(constraints)
   .build()

Java

OneTimeWorkRequest cache = new OneTimeWorkRequest.Builder(PlantWorker.class)
       .setInputMerger(ArrayCreatingInputMerger.class)
       .setConstraints(constraints)
       .build();

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

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

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

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

שרשור וסטטוסים של עבודה

שרשראות של OneTimeWorkRequest מופעלות ברצף כל עוד העבודה שלהן מסתיימת בהצלחה (כלומר, הן מחזירות Result.success()). בקשות עבודה עלולות להיכשל או להתבטל בזמן הריצה, ויש לכך השפעות על בקשות עבודה תלויות.

כשהבקשה הראשונה של OneTimeWorkRequest נכנסת לתור בשרשרת של בקשות עבודה, כל בקשות העבודה הבאות נחסמות עד שהעבודה של בקשת העבודה הראשונה מסתיימת.

דיאגרמה שמציגה שרשרת של משימות. המשימה הראשונה נכנסת לתור, וכל המשימות הבאות נחסמות עד שהמשימה הראשונה מסתיימת.

אחרי שהבקשה נכנסת לתור וכל האילוצים של העבודה מתקיימים, בקשת העבודה הראשונה מתחילה לפעול. אם העבודה הושלמה בהצלחה ב-OneTimeWorkRequest או ב-List<OneTimeWorkRequest> ברמה הבסיסית (כלומר, היא מחזירה Result.success()), הקבוצה הבאה של בקשות העבודה התלויות תתווסף לתור.

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

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

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

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

מידע נוסף על הגדרת אסטרטגיות ניסיון חוזר בהתאמה אישית זמין במאמר מדיניות ניסיון חוזר והשהיה.

אם מדיניות הניסיונות החוזרים לא מוגדרת או מוצתה, או אם מגיעים למצב שבו OneTimeWorkRequest מחזיר Result.failure(), בקשת העבודה הזו וכל בקשות העבודה שתלויות בה מסומנות כ-FAILED.

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

אותו היגיון חל כשמבטלים OneTimeWorkRequest. כל בקשות העבודה התלויות מסומנות גם הן כ-CANCELLED והעבודה שלהן לא תבוצע.

דיאגרמה שמציגה שרשרת של משימות. משימה אחת בוטלה. כתוצאה מכך, כל המשימות שאחריה בשרשרת מבוטלות גם הן.

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

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

למידע נוסף, קראו את המאמר ביטול והפסקה של עבודה.