עבודות שרשור

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

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

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

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

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

נבחן עכשיו דוגמה. בדוגמה הזו, 3 משימות שונות של 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 versucht, die Eingaben zu verschmelzen und Arrays zu erstellen, wenn nötig.

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

OverwritingInputMerger

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

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

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

אם יש מחלוקת, העובד האחרון שהשלים את ה'מנצח' והערך שלו מועבר אל cache.

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

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

ArrayCreatingInputMerger

בדוגמה שלמעלה, מכיוון שאנחנו רוצים לשמור את הפלט מכל העובדים של plantname, צריך להשתמש ב-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()), המערכת תוסיף לתור את הקבוצה הבאה של בקשות העבודה התלויות.

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

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

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

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

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

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

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

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

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

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

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

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