কম্পিউটার টিউটোরিয়াল

রুবিতে অ্যাসিঙ্ক্রোনাস থ্রেড টেস্টিং মাস্টার করা: বেস্ট প্র্যাকটিস এবং প্যাটার্ন

থ্রেড এবং অ্যাসিঙ্ক্রোনাস এনভায়রনমেন্ট প্রাথমিকভাবে কিছুটা ট্রিকি। একটি ভালো মেন্টাল মডেল ছাড়া ইন্টারঅ্যাকশন অর্গানাইজ করতে, সহজে সমস্যায় পড়া যায় এবং অনাকাঙ্ক্ষিত ফলাফলে ফিনিশ হয়। এর উপরে, অ্যাসিঙ্ক্রোনাস কোড টেস্ট করা কঠিন সঠিক টুল বা টেস্ট প্যাটার্ন ছাড়া।

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

আপনি যদি রেইলস বা র্যাক বা সত্যি যেকোনো অ্যাপ্লিকেশন ব্যবহার করেন যেটির ওয়েব ব্রাউজার ফ্রন্ট এন্ড আছে, আপনি একটি অ্যাসিঙ্ক্রোনাস এনভায়রনমেন্টে আছেন। Rack #call সবসময় অ্যাসিঙ্ক্রোনাসলি কল হয়। তাই আপনি জেনেন বা না জানেন, আপনার মাল্টিথ্রেডেড কম্পোনেন্ট ব্যবহার করার ভালো চান্স আছে।

টেস্টিং: ট্রিগার, কালেক্ট এবং চেক

একটি অ্যাসিঙ্ক্রোনাস কলব্যাক API টেস্টিং সিনক্রোনাস করা যেতে পারে তিনটি স্টেপের একটি প্যাটার্ন ফলো করে; ট্রিগার, কালেক্ট, এবং চেক। প্রতিটি থ্রেডকে আলাদা ব্যক্তি এবং অবজেক্টকে, কুয়ashi, জিনিস হিসেবে চিন্তা করুন যেগুলো শুধু একজন ব্যক্তির কাছে একবারে ওনারশিপে থাকতে পারে।

আমরা ব্যাটম্যান এবং তার ৭টি আলাদা সুটের উদাহরণ ব্যবহার করব। কারণ এটি একটি প্র্যাকটিক্যাল উদাহরণ এবং আমরা বুঝতে পারি কত গুরুত্বপূর্ণ জানা যে সব সুট আলফ্রেডের কাছে ধুলো কাটায় যখন আপনি সিটি বাঁচাতে বের হচ্ছেন।

উদাহরণ: ব্যাটকেভে লন্ড্রি দিবস

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

class SuitWashScheduler def initialize(cnt) Thread.new { cnt.times { sleep(1.0) yield } } end end

ফলাফল কালেক্ট করা

রেজাল্ট কালেক্ট করা থ্রেড-সেফ হতে হবে রেস কন্ডিশন এড়াতে। একাধিক থ্রেডের মধ্যে শেয়ার করা যেকোনো অবজেক্ট প্রোটেক্টেড হতে হবে। প্রোটেকশন হলো এক অবজেক্টের ওনার ট্র্যাক রাখার উপায়। শুধু ওনারই পরিবর্তন করতে পারে বা ভিউ করতে পারে অবজেক্টটি। একটি সুট শুধু ব্যাটম্যানের কাছে থাকতে পারে ফাইটে ব্যবহার করতে, অথবা আলফ্রেডের কাছে ধুলো কাটাতে।

ফ্রেন্ডলি থাকতে একটি থ্রেড (রূপক 알ফ্রেড বা ব্যাটম্যান) শুধু ছোট সময়ের জন্য ওনারশিপ নেয় এবং তারপর ওনারশিপ ছাড়ে দেয়। একটি Mutex সাধারণত ব্যবহৃত হয় ওনার ট্র্যাক রাখতে। SuitWashScheduler কলব্যাক রেজাল্ট কাউন্টারের ওনারশিপ নেয় যখন কাউন্টার ইনক্রিমেন্ট হয়। SuitWashScheduler থ্রেডে চলা কলব্যাক সিগন্যাল দেয় যে সকল রেজাল্ট রিসিভ করা হয়েছে যখন কাউন্টার টার্গেটে পৌঁছায়।

উদাহরণ লিখতে শুরু করি কিছু গ্লোবাল সেট আপ করি। একটি রিয়েল অ্যাপ্লিকেশনে গ্লোবালগুলো ক্লাস বা অবজেক্ট অ্যাট্রিবিউট দ্বারা রিপ্লেস করা হয়।

$main_thread = Thread.current $mu = Mutex.new $count = 0 $target = 7

ম্যানেজমেন্ট এবং ওনাররা

$main_thread এবং $mu থ্রেড ম্যানেজ করতে এবং টেস্ট কমপ্লিশন জন্য অপেক্ষা করতে ব্যবহৃত হয় যখন $target এবং $count টেস্ট রেজাল্ট ট্র্যাক করে। মনে রাখবেন এটি একটি טרিভিয়াল টেস্ট তাই রেজাল্ট কালেক্ট এবং চেক করা সিম্পল হতে হবে।

টেস্ট শুরু হয় SuitWashScheduler-এর একটি নতুন ইনস্ট্যান্স তৈরি করে, ইনিশিয়ালাইজারকে $target ইটেরেশনের সংখ্যা দিয়ে। এই কেসে, ৭টি সুট যেগুলো ধোয়া দরকার। প্রদত্ত ব্লকটি SuitWashScheduler থ্রেডে রান হবে। প্রতিটি ইটেরেশনে $count ইনক্রিমেন্ট হবে এবং প্রিন্ট হবে।

আগে দেখি আমরা বুঝতে পারি মেইন, টেস্ট থ্রেড $count-ও চেক করবে যেটিও মানে $count-এর ওনারশিপ লাগবে সেটাও তাই $count-এর ওনারশিপ নেওয়ার উপায় দরকার। $mu Mutex ইনস্ট্যান্স হলো ওনারশিপ টোকেন। SuitWashScheduler.new কলে পাস করা ব্লকে একটি $mu.synchronize ব্লক ওনারশিপ নেয় যথেষ্ট সময় $count সেট করতে এবং রেজাল্ট চেক করতে। রেজাল্ট চেক সম্পর্কে একটু পর আরও।

SuitWashScheduler.new($target) { $mu.synchronize { $count += 1 puts $count $main_thread.wakeup if $target <= $count } }

চেক: সব সুট ডান হয়েছে কিনা?

মেইন থ্রেডে ফিরে, আমাদের টেস্ট ফিনিশ হওয়ার জন্য অপেক্ষা করতে হবে। ব্যাটম্যানকে অপেক্ষা করতে হবে সব ৭টি সুট ডান হওয়ার আগে। চেক করার দুটি কন্ডিশন আছে; টেস্ট $count আপডেট করছে এক্সপেক্টেডলি বা ব্যাটম্যান বোর होकर টেস্ট ফিনিশ হওয়ার জন্য অপেক্ষা করছে এবং টাইম আউট হয়। $count চেক করার আগে যেন সেটি $target-এ পৌঁছেছে কিনা, $count-এর ওনারশিপ দরকার। ঠিক SuitWashScheduler-এর ব্লকের মত $mu.synchronize কল ব্যবহার করা হয়।

কিন্তু এটা সঠিক নয়, যদি আমরা মেইন থ্রেড লক করি, SuitWashScheduler থ্রেড কীভাবে $count পরিবর্তন করবে? ভাগ্যবশত, আমাদের জন্য একটি সুন্দর ট্রিক আছে যা এই সমস্যা সমাধান করে। Mutex ক্লাসে একটি #sleep মেথড আছে যা ওনারশিপ ছাড়ে দেয় এবং অপেক্ষা করে যতক্ষণ না টাইম আউট হয় বা ওয়েক আপ হয়। একবার ওয়েক আপ হলে হয় টাইমআউট বা মেইন থ্রেডে #wakeup কল দিয়ে $mu আবার ওনারশিপ নেওয়ার চেষ্টা করে কন্টিনিউ করার আগে। একবার ওনারশিপ অর্জন হলে, রেজাল্ট চেক করা যায় এবং টেস্টের পাস বা ফেইল স্টেট নির্ধারণ করা যায়।

$mu.synchronize { $mu.sleep($target + 1) if $target != $count puts 'FAILED' else puts 'Passed! All suits are washed and clean' end }

আপনি যদি একটু গভীরে যেতে চান, আপনি উদাহরণটি কিছুটা আরও ইন্টারেস্টিং বানাতে পারেন একাধিক শিডিউলার তৈরি করে এবং দেখতে পারেন কীভাবে Mutex $count চেঞ্জগুলো কোলাইড হতে বাধা দেয়। যেন ব্যাটম্যান কিছু সুট আলফ্রেডকে পাঠায় ধুলো কাটাতে, এবং কিছু অন্য ড্রাই ক্লিনার্সে। লজিক পরিবর্তন করতে ভুলবেন না যাতে $target চেকটি সব এক্সপেক্টেড yield-এর টোটাল হয়।

মোড়া

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

আমরা আশা করি উদাহরণগুলো আপনাকে অ্যাসিঙ্ক্রোনাস মেকানিজম মনে রাখতে সাহায্য করবে, কিন্তু আমরা আশা করি ব্যাটম্যান ডরেছে যখন তার সব সুট ধুলো কাটা হচ্ছে সেই ইমেজ আপনার সাথে বেশি দিন থাকবে না।

P.S. আপনি যদি ব্লগে সব ব্যাটম্যান রূপক দিয়ে ফ니শ হয়ে যান, আমাদের জানান।

  1. রুবিতে AWS Lambda: এন্ড-টু-এন্ড বিল্ড, টেস্ট এবং ডিপ্লয় গাইড

  2. টেস্ট-কমিট-রিভার্ট: লিগ্যাসি রুবি কোড নিরাপদে টেস্ট করার প্র্যাকটিক্যাল ওয়ার্কফ্লো

  3. রুবি ২.৬-এ ৯টি গুরুত্বপূর্ণ উন্নতির অন্বেষণ

  4. রুবি থ্রেড মাস্টার করুন: মাল্টিথ্রেডিং-এর একটি বিগিনার-ফ্রেন্ডলি গাইড