চেইনিং কাজ

WorkManager আপনাকে কাজের একটি শৃঙ্খল তৈরি ও সারিতে যুক্ত করার সুযোগ দেয়, যা একাধিক নির্ভরশীল কাজ নির্দিষ্ট করে এবং সেগুলো কোন ক্রমে চলবে তা নির্ধারণ করে দেয়। এই কার্যকারিতাটি বিশেষভাবে উপযোগী যখন আপনাকে বেশ কয়েকটি কাজ একটি নির্দিষ্ট ক্রমে চালাতে হয়।

কাজের একটি ধারা তৈরি করতে, আপনি WorkManager.beginWith(OneTimeWorkRequest) অথবা WorkManager.beginWith(List<OneTimeWorkRequest>) ব্যবহার করতে পারেন, যেগুলোর প্রতিটিই WorkContinuation এর একটি ইনস্ট্যান্স রিটার্ন করে।

এরপর একটি WorkContinuation ব্যবহার করে then(OneTimeWorkRequest) অথবা then(List<OneTimeWorkRequest>) -এর মাধ্যমে নির্ভরশীল OneTimeWorkRequest ইনস্ট্যান্স যোগ করা যেতে পারে।

WorkContinuation.then(...) এর প্রতিটি প্রয়োগ WorkContinuation এর একটি নতুন ইনস্ট্যান্স ফেরত দেয়। আপনি যদি OneTimeWorkRequest ইনস্ট্যান্সের একটি List যোগ করেন, তাহলে এই অনুরোধগুলি সমান্তরালভাবে চলতে পারে।

অবশেষে, আপনি আপনার WorkContinuation গুলোর চেইনকে enqueue() জন্য WorkContinuation.enqueue() মেথডটি ব্যবহার করতে পারেন।

চলুন একটি উদাহরণ দেখা যাক। এই উদাহরণে, ৩টি ভিন্ন ওয়ার্কার জব চালানোর জন্য কনফিগার করা হয়েছে (সম্ভবত সমান্তরালভাবে)। এরপর এই ওয়ার্কারগুলোর ফলাফল একত্রিত করে একটি ক্যাশিং ওয়ার্কার জবে পাঠানো হয়। সবশেষে, সেই জবের আউটপুট একটি আপলোড ওয়ার্কারে পাঠানো হয়, যা ফলাফলগুলো একটি রিমোট সার্ভারে আপলোড করে।

কোটলিন

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()

জাভা

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 ব্যবহার করে।

WorkManager দুই ধরনের InputMerger প্রদান করে থাকে:

  • OverwritingInputMerger সমস্ত ইনপুট থেকে সমস্ত কী আউটপুটে যোগ করার চেষ্টা করে। কোনো বিরোধের ক্ষেত্রে, এটি পূর্বে সেট করা কীগুলিকে ওভাররাইট করে দেয়।

  • ArrayCreatingInputMerger ইনপুটগুলোকে একত্রিত করার চেষ্টা করে এবং প্রয়োজনে অ্যারে তৈরি করে।

আপনার যদি আরও সুনির্দিষ্ট কোনো ব্যবহারের ক্ষেত্র থাকে, তাহলে আপনি InputMerger সাবক্লাস করে নিজের কোড লিখতে পারেন।

ওভাররাইটিংইনপুটমার্জার

OverwritingInputMerger হলো ডিফল্ট মার্জার পদ্ধতি। মার্জারের সময় কোনো কী-এর মধ্যে দ্বন্দ্ব দেখা দিলে, ফলাফলস্বরূপ প্রাপ্ত আউটপুট ডেটাতে কোনো কী-এর সর্বশেষ মান তার পূর্ববর্তী সংস্করণগুলোকে ওভাররাইট করে দেবে।

উদাহরণস্বরূপ, যদি প্ল্যান্ট ইনপুটগুলির প্রতিটিতে তাদের নিজ নিজ ভেরিয়েবল নামের ( "plantName1" , "plantName2" , এবং "plantName3" ) সাথে মেলে এমন একটি কী থাকে, তাহলে cache ওয়ার্কারে পাঠানো ডেটাতে তিনটি কী-ভ্যালু পেয়ার থাকবে।

ডায়াগ্রামটিতে দেখানো হয়েছে যে তিনটি জব চেইনের পরবর্তী জবে ভিন্ন ভিন্ন আউটপুট পাঠাচ্ছে। যেহেতু তিনটি আউটপুটেরই কী (key) ভিন্ন, তাই পরবর্তী জবটি তিনটি কী/ভ্যালু পেয়ার (key/value pair) গ্রহণ করে।

যদি কোনো দ্বন্দ্ব দেখা দেয়, তাহলে সর্বশেষ সম্পন্নকারী কর্মীটিই বিজয়ী হয় এবং তার মান cache ) পাঠানো হয়।

ডায়াগ্রামটিতে দেখানো হয়েছে কীভাবে তিনটি জব চেইনের পরবর্তী জবের কাছে তাদের আউটপুট পাঠাচ্ছে। এক্ষেত্রে, ওই জবগুলোর মধ্যে দুটি একই কী (key) সহ আউটপুট তৈরি করে। ফলে, পরবর্তী জবটি দুটি কী/ভ্যালু পেয়ার পায়, এবং সাংঘর্ষিক আউটপুটগুলোর মধ্যে একটি বাদ পড়ে যায়।

যেহেতু আপনার কাজের অনুরোধগুলো সমান্তরালভাবে চলে, তাই এটি কোন ক্রমে চলবে তার কোনো নিশ্চয়তা থাকে না। উপরের উদাহরণে, plantName1 এর মান "tulip" বা "elm" হতে পারে, যা নির্ভর করে কোন মানটি শেষে লেখা হয়েছে তার উপর। যদি কী-কনফ্লিক্টের (key conflict) সম্ভাবনা থাকে এবং একটি মার্জারে (merger) সমস্ত আউটপুট ডেটা সংরক্ষণ করার প্রয়োজন হয়, তাহলে ArrayCreatingInputMerger একটি ভালো বিকল্প হতে পারে।

ArrayCreatingInputMerger

উপরের উদাহরণটির ক্ষেত্রে, যেহেতু আমরা প্ল্যান্ট নামের সমস্ত Workers-এর আউটপুটগুলো সংরক্ষণ করতে চাই, তাই আমাদের ArrayCreatingInputMerger ব্যবহার করা উচিত।

কোটলিন

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

জাভা

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

ArrayCreatingInputMerger প্রতিটি কী-কে একটি অ্যারের সাথে যুক্ত করে। যদি প্রতিটি কী অনন্য হয়, তাহলে আপনার ফলাফল হবে এক-উপাদান বিশিষ্ট একাধিক অ্যারে।

ডায়াগ্রামটিতে দেখানো হয়েছে যে তিনটি জব চেইনের পরবর্তী জবে ভিন্ন ভিন্ন আউটপুট পাঠাচ্ছে। পরবর্তী জবে তিনটি অ্যারে পাঠানো হয়, প্রতিটি আউটপুট কী-এর জন্য একটি করে। প্রতিটি অ্যারেতে একটিমাত্র মেম্বার রয়েছে।

যদি কোনো কী-এর মধ্যে সংঘর্ষ হয়, তাহলে সংশ্লিষ্ট মানগুলোকে একটি অ্যারেতে একত্রিত করা হয়।

ডায়াগ্রামটিতে দেখানো হয়েছে কীভাবে তিনটি জব চেইনের পরবর্তী জবে তাদের আউটপুট পাঠাচ্ছে। এক্ষেত্রে, ওই জবগুলোর মধ্যে দুটি একই 'কী' (key) ব্যবহার করে আউটপুট তৈরি করে। পরবর্তী জবটিকে দুটি অ্যারে পাঠানো হয়, প্রতিটি 'কী'-এর জন্য একটি করে। ওই অ্যারেগুলোর একটিতে দুটি মেম্বার থাকে, কারণ ওই 'কী' দিয়ে দুটি আউটপুট তৈরি হয়েছিল।

শৃঙ্খল এবং কাজের অবস্থা

OneTimeWorkRequest এর চেইনগুলো ক্রমানুসারে চলতে থাকে যতক্ষণ না তাদের কাজ সফলভাবে সম্পন্ন হয় (অর্থাৎ, তারা একটি Result.success() রিটার্ন করে)। চলার সময় ওয়ার্ক রিকোয়েস্টগুলো ব্যর্থ হতে পারে বা বাতিল হয়ে যেতে পারে, যার ফলে নির্ভরশীল ওয়ার্ক রিকোয়েস্টগুলোর উপর পরবর্তী প্রভাব পড়ে।

যখন একাধিক কাজের অনুরোধের একটি শৃঙ্খলে প্রথম OneTimeWorkRequest সারিবদ্ধ করা হয়, তখন সেই প্রথম কাজের অনুরোধটির কাজ সম্পন্ন না হওয়া পর্যন্ত পরবর্তী সমস্ত কাজের অনুরোধ অবরুদ্ধ থাকে।

কাজের একটি শৃঙ্খল দেখানো চিত্র। প্রথম কাজটি সারিতে যুক্ত করা হয়; প্রথমটি শেষ না হওয়া পর্যন্ত পরবর্তী সমস্ত কাজ অবরুদ্ধ থাকে।

একবার কিউতে যুক্ত হলে এবং কাজের সমস্ত শর্ত পূরণ হলে, প্রথম ওয়ার্ক রিকোয়েস্টটি চলতে শুরু করে। যদি রুট OneTimeWorkRequest বা List<OneTimeWorkRequest> এ কাজটি সফলভাবে সম্পন্ন হয় (অর্থাৎ, এটি Result.success() রিটার্ন করে), তাহলে পরবর্তী নির্ভরশীল ওয়ার্ক রিকোয়েস্টগুলো কিউতে যুক্ত হবে।

কাজের একটি শৃঙ্খল দেখানো ডায়াগ্রাম। প্রথম কাজটি সফল হয়েছে এবং এর ঠিক পরের দুটি কাজ সারিতে যুক্ত হয়েছে। বাকি কাজগুলো তাদের পূর্ববর্তী কাজগুলো শেষ না হওয়া পর্যন্ত আটকে আছে।

যতক্ষণ প্রতিটি কাজের অনুরোধ সফলভাবে সম্পন্ন হয়, এই একই ধারা আপনার কাজের অনুরোধের শৃঙ্খলের বাকি অংশ জুড়ে চলতে থাকে, যতক্ষণ না শৃঙ্খলের সমস্ত কাজ সম্পন্ন হয়। যদিও এটিই সবচেয়ে সহজ এবং প্রায়শই পছন্দনীয় পরিস্থিতি, ত্রুটিপূর্ণ অবস্থাগুলোও সামলানো ঠিক ততটাই গুরুত্বপূর্ণ।

যখন কোনো কর্মী আপনার কাজের অনুরোধটি প্রক্রিয়া করার সময় কোনো ত্রুটি ঘটে, তখন আপনি আপনার সংজ্ঞায়িত একটি ব্যাকঅফ নীতি অনুসারে সেই অনুরোধটি পুনরায় চেষ্টা করতে পারেন। একটি চেইনের অংশ এমন কোনো অনুরোধ পুনরায় চেষ্টা করার অর্থ হলো, শুধুমাত্র সেই অনুরোধটিই তার জন্য প্রদত্ত ইনপুট ডেটা দিয়ে পুনরায় চেষ্টা করা হবে। সমান্তরালভাবে চলমান কোনো কাজ এতে প্রভাবিত হবে না।

কাজের একটি শৃঙ্খল দেখানো ডায়াগ্রাম। কাজগুলোর মধ্যে একটি ব্যর্থ হয়েছে, কিন্তু এর জন্য একটি ব্যাকঅফ পলিসি সংজ্ঞায়িত করা ছিল। নির্দিষ্ট পরিমাণ সময় অতিবাহিত হওয়ার পর কাজটি পুনরায় চলবে। শৃঙ্খলে এর পরবর্তী কাজগুলো ব্লক হয়ে থাকবে যতক্ষণ না এটি সফলভাবে সম্পন্ন হয়।

কাস্টম রিট্রাই স্ট্র্যাটেজি নির্ধারণ সম্পর্কে আরও তথ্যের জন্য, রিট্রাই অ্যান্ড ব্যাকঅফ পলিসি দেখুন।

যদি সেই পুনঃপ্রচেষ্টা নীতিটি অনির্ধারিত বা নিঃশেষিত হয়, অথবা আপনি অন্য কোনোভাবে এমন কোনো অবস্থায় পৌঁছান যেখানে একটি OneTimeWorkRequest Result.failure() রিটার্ন করে, তাহলে সেই ওয়ার্ক রিকোয়েস্ট এবং এর উপর নির্ভরশীল সমস্ত ওয়ার্ক রিকোয়েস্টকে FAILED.

কাজের একটি শৃঙ্খল দেখানো চিত্র। একটি কাজ ব্যর্থ হয়েছে এবং পুনরায় চেষ্টা করা যাবে না। ফলে, শৃঙ্খলে থাকা এর পরের সমস্ত কাজও ব্যর্থ হয়ে যায়।

যখন কোনো OneTimeWorkRequest বাতিল করা হয়, তখনও একই যুক্তি প্রযোজ্য। এর উপর নির্ভরশীল যেকোনো ওয়ার্ক রিকোয়েস্টকেও CANCELLED হিসেবে চিহ্নিত করা হয় এবং সেগুলোর কাজ সম্পাদিত হয় না।

কাজের একটি শৃঙ্খল দেখানো চিত্র। একটি কাজ বাতিল করা হয়েছে। ফলে, শৃঙ্খলে এর পরের সমস্ত কাজও বাতিল হয়ে গেছে।

মনে রাখবেন যে, যদি আপনি এমন কোনো চেইনে আরও কাজের অনুরোধ যুক্ত করেন যেখানে ইতিমধ্যেই কাজ ব্যর্থ বা বাতিল করা হয়েছে, তাহলে আপনার নতুন যুক্ত করা কাজের অনুরোধটিও যথাক্রমে FAILED বা CANCELLED হিসেবে চিহ্নিত হবে। যদি আপনি একটি বিদ্যমান চেইনের কাজ প্রসারিত করতে চান, তাহলে ExistingWorkPolicy- এর APPEND_OR_REPLACE দেখুন।

কাজের অনুরোধের শৃঙ্খল তৈরি করার সময়, নির্ভরশীল কাজের অনুরোধগুলিতে পুনরায় চেষ্টার নীতি (retry policies) নির্ধারণ করা উচিত, যাতে কাজটি সর্বদা সময়মতো সম্পন্ন হয়। ব্যর্থ কাজের অনুরোধের ফলে শৃঙ্খল অসম্পূর্ণ থাকতে পারে এবং/অথবা অপ্রত্যাশিত অবস্থা তৈরি হতে পারে।

আরও তথ্যের জন্য, কাজ বাতিল করা এবং বন্ধ করা দেখুন।