একটি Python 2 অ্যাপ ইঞ্জিন ক্লাউড NDB & পাইথন 3 এবং ক্লাউড ডেটাস্টোরে ক্লাউড টাস্ক অ্যাপ (মডিউল 9)

১. সংক্ষিপ্ত বিবরণ

সার্ভারলেস মাইগ্রেশন স্টেশন সিরিজের কোডল্যাব (স্ব-গতিতে শেখার উপযোগী টিউটোরিয়াল) এবং সম্পর্কিত ভিডিওগুলোর লক্ষ্য হলো গুগল ক্লাউড সার্ভারলেস ডেভেলপারদের এক বা একাধিক মাইগ্রেশনের মাধ্যমে তাদের অ্যাপ্লিকেশনগুলোকে আধুনিক করে তুলতে সাহায্য করা, যার মূল উদ্দেশ্য হলো পুরোনো সার্ভিসগুলো থেকে সরে আসা। এটি আপনার অ্যাপগুলোকে আরও সহজে বহনযোগ্য করে তোলে এবং আপনাকে আরও বেশি বিকল্প ও নমনীয়তা দেয়, যার ফলে আপনি আরও বিস্তৃত পরিসরের ক্লাউড প্রোডাক্টের সাথে ইন্টিগ্রেট করতে ও সেগুলো ব্যবহার করতে পারেন এবং নতুন ল্যাঙ্গুয়েজ রিলিজে আরও সহজে আপগ্রেড করতে পারেন। যদিও প্রাথমিকভাবে এই সিরিজটি ক্লাউডের একেবারে প্রথম দিকের ব্যবহারকারী, অর্থাৎ অ্যাপ ইঞ্জিন (স্ট্যান্ডার্ড এনভায়রনমেন্ট) ডেভেলপারদের উপর দৃষ্টি নিবদ্ধ করে তৈরি, তবে এর পরিধি এতটাই বিস্তৃত যে এটি ক্লাউড ফাংশনস এবং ক্লাউড রান- এর মতো অন্যান্য সার্ভারলেস প্ল্যাটফর্ম বা প্রযোজ্য ক্ষেত্রে অন্য প্ল্যাটফর্মগুলোকেও অন্তর্ভুক্ত করতে পারে।

এই কোডল্যাবের উদ্দেশ্য হলো মডিউল ৮-এর স্যাম্পল অ্যাপটিকে পাইথন ৩-এ পোর্ট করা, সেইসাথে ডেটাস্টোর (ডেটাস্টোর মোডে থাকা ক্লাউড ফায়ারস্টোর) অ্যাক্সেসের জন্য ক্লাউড এনডিবি-র পরিবর্তে নেটিভ ক্লাউড ডেটাস্টোর ক্লায়েন্ট লাইব্রেরি ব্যবহার করা এবং ক্লাউড টাস্কস ক্লায়েন্ট লাইব্রেরিকে সর্বশেষ সংস্করণে আপগ্রেড করা।

আমরা মডিউল ৭-এ পুশ টাস্কের জন্য টাস্ক কিউ-এর ব্যবহার যুক্ত করেছিলাম, তারপর মডিউল ৮-এ সেই ব্যবহারটি ক্লাউড টাস্ক-এ স্থানান্তরিত করেছি। এখানে মডিউল ৯-এ, আমরা পাইথন ৩ এবং ক্লাউড ডেটাস্টোর নিয়ে আলোচনা চালিয়ে যাব। যারা পুল টাস্কের জন্য টাস্ক কিউ ব্যবহার করেন, তারা ক্লাউড পাব/সাব-এ স্থানান্তরিত হবেন এবং তাদের পরিবর্তে মডিউল ১৮-১৯ দেখতে হবে।

আপনি শিখবেন কিভাবে

  • মডিউল ৮-এর নমুনা অ্যাপটিকে পাইথন ৩-এ পোর্ট করুন
  • ক্লাউড এনডিবি থেকে ক্লাউড ডেটাস্টোর ক্লায়েন্ট লাইব্রেরিতে ডেটাস্টোর অ্যাক্সেস পরিবর্তন করুন
  • ক্লাউড টাস্ক ক্লায়েন্ট লাইব্রেরির সর্বশেষ সংস্করণে আপগ্রেড করুন

আপনার যা যা লাগবে

জরিপ

আপনি এই টিউটোরিয়ালটি কীভাবে ব্যবহার করবেন?

শুধু একবার পড়ে দেখুন এটি পড়ুন এবং অনুশীলনগুলো সম্পূর্ণ করুন।

পাইথন নিয়ে আপনার অভিজ্ঞতাকে আপনি কীভাবে মূল্যায়ন করবেন?

শিক্ষানবিশ মধ্যবর্তী দক্ষ

গুগল ক্লাউড পরিষেবা ব্যবহারের অভিজ্ঞতাকে আপনি কীভাবে মূল্যায়ন করবেন?

শিক্ষানবিশ মধ্যবর্তী দক্ষ

২. পটভূমি

মডিউল ৭-এ দেখানো হয়েছে কিভাবে পাইথন ২ ফ্লাস্ক অ্যাপ ইঞ্জিন অ্যাপে অ্যাপ ইঞ্জিন টাস্ক কিউ পুশ টাস্ক ব্যবহার করতে হয়। মডিউল ৮- এ, আপনি সেই অ্যাপটিকে টাস্ক কিউ থেকে ক্লাউড টাস্কে মাইগ্রেট করবেন। এখানে মডিউল ৯- এ, আপনি সেই যাত্রা অব্যাহত রাখবেন এবং অ্যাপটিকে পাইথন ৩-এ পোর্ট করার পাশাপাশি ডেটাস্টোর অ্যাক্সেসের জন্য ক্লাউড এনডিবি-র পরিবর্তে নেটিভ ক্লাউড ডেটাস্টোর ক্লায়েন্ট লাইব্রেরি ব্যবহার শুরু করবেন।

যেহেতু ক্লাউড এনডিবি পাইথন ২ এবং ৩ উভয়ের জন্যই কাজ করে, তাই যেসব অ্যাপ ইঞ্জিন ব্যবহারকারী তাদের অ্যাপ পাইথন ২ থেকে ৩-এ পোর্ট করছেন, তাদের জন্য এটি যথেষ্ট। ক্লায়েন্ট লাইব্রেরিগুলোকে ক্লাউড ডেটাস্টোরে অতিরিক্ত মাইগ্রেশন করা সম্পূর্ণ ঐচ্ছিক , এবং এটি বিবেচনা করার একটিই কারণ আছে: আপনার এমন নন-অ্যাপ ইঞ্জিন অ্যাপ (এবং/অথবা পাইথন ৩ অ্যাপ ইঞ্জিন অ্যাপ) আছে যা ইতিমধ্যেই ক্লাউড ডেটাস্টোর ক্লায়েন্ট লাইব্রেরি ব্যবহার করছে এবং আপনি আপনার কোডবেসকে একত্রিত করে শুধুমাত্র একটি ক্লায়েন্ট লাইব্রেরির মাধ্যমে ডেটাস্টোর অ্যাক্সেস করতে চান। ক্লাউড এনডিবি বিশেষভাবে পাইথন ২ অ্যাপ ইঞ্জিন ডেভেলপারদের জন্য একটি পাইথন ৩ মাইগ্রেশন টুল হিসেবে তৈরি করা হয়েছিল, তাই আপনার কোডে যদি ইতিমধ্যেই ক্লাউড ডেটাস্টোর ক্লায়েন্ট লাইব্রেরি ব্যবহৃত না থাকে, তবে এই মাইগ্রেশনটি বিবেচনা করার কোনো প্রয়োজন নেই।

অবশেষে, ক্লাউড টাস্কস ক্লায়েন্ট লাইব্রেরির উন্নয়ন শুধুমাত্র পাইথন ৩-এ অব্যাহত রয়েছে, তাই আমরা পাইথন ২-এর সর্বশেষ সংস্করণগুলোর একটি থেকে এর সমসাময়িক পাইথন ৩ সংস্করণে "স্থানান্তরিত" হচ্ছি। সৌভাগ্যবশত, পাইথন ২ থেকে এতে কোনো বড় ধরনের পরিবর্তন নেই, যার অর্থ হলো এক্ষেত্রে আপনার আর কিছু করার প্রয়োজন নেই।

এই টিউটোরিয়ালটিতে নিম্নলিখিত ধাপগুলো রয়েছে:

  1. প্রস্তুতি/পূর্বপ্রস্তুতি
  2. কনফিগারেশন আপডেট করুন
  3. অ্যাপ্লিকেশন কোড পরিবর্তন করুন

৩. প্রস্তুতি/পূর্বপ্রস্তুতি

এই বিভাগে ব্যাখ্যা করা হয়েছে কীভাবে:

  1. আপনার ক্লাউড প্রজেক্ট সেট আপ করুন
  2. বেসলাইন নমুনা অ্যাপ পান
  3. বেসলাইন অ্যাপ পুনরায় স্থাপন এবং যাচাই করুন

এই পদক্ষেপগুলো নিশ্চিত করে যে আপনি একটি কার্যকর কোড দিয়ে কাজ শুরু করছেন এবং এটি ক্লাউড পরিষেবাগুলিতে স্থানান্তরের জন্য প্রস্তুত।

১. প্রকল্প স্থাপন করুন

আপনি যদি মডিউল ৮-এর কোডল্যাবটি সম্পন্ন করে থাকেন, তাহলে সেই একই প্রজেক্ট (এবং কোড) পুনরায় ব্যবহার করুন। বিকল্পভাবে, একটি সম্পূর্ণ নতুন প্রজেক্ট তৈরি করুন অথবা অন্য কোনো বিদ্যমান প্রজেক্ট পুনরায় ব্যবহার করুন। নিশ্চিত করুন যে প্রজেক্টটিতে একটি সক্রিয় বিলিং অ্যাকাউন্ট এবং একটি চালু করা অ্যাপ ইঞ্জিন অ্যাপ রয়েছে। আপনার প্রজেক্ট আইডিটি খুঁজে বের করুন, কারণ এই কোডল্যাবের সময় এটি আপনার হাতের কাছে প্রয়োজন হবে এবং যখনই PROJECT_ID ভেরিয়েবলটির সম্মুখীন হবেন, তখনই এটি ব্যবহার করতে হবে।

২. বেসলাইন নমুনা অ্যাপটি নিন

পূর্বশর্তগুলোর মধ্যে একটি হলো একটি কার্যকর মডিউল ৮ অ্যাপ ইঞ্জিন অ্যাপ: মডিউল ৮ কোডল্যাবটি সম্পূর্ণ করুন (প্রস্তাবিত) অথবা রিপো থেকে মডিউল ৮ অ্যাপটি কপি করুন। আপনি আপনার নিজের বা আমাদের, যেটিই ব্যবহার করুন না কেন, আমরা মডিউল ৮ কোড থেকেই শুরু করব ("START")। এই কোডল্যাবটি আপনাকে মাইগ্রেশনের পুরো প্রক্রিয়াটি ধাপে ধাপে দেখাবে এবং শেষে এমন একটি কোড থাকবে যা মডিউল ৯ রিপো ফোল্ডারের কোডের অনুরূপ ("FINISH")।

আপনি মডিউল ৭-এর যে অ্যাপই ব্যবহার করুন না কেন, ফোল্ডারটি নিচের মতো দেখতে হবে, সম্ভবত এর সাথে একটি lib ফোল্ডারও থাকবে:

$ ls
README.md               appengine_config.py     requirements.txt
app.yaml                main.py                 templates

৩. বেসলাইন অ্যাপ (পুনরায়) স্থাপন এবং যাচাই করুন

মডিউল ৮ অ্যাপটি ডেপ্লয় করতে নিম্নলিখিত ধাপগুলো অনুসরণ করুন:

  1. যদি lib ফোল্ডার থাকে তবে তা মুছে ফেলুন এবং lib পুনরায় তৈরি করতে pip install -t lib -r requirements.txt চালান। আপনার ডেভেলপমেন্ট মেশিনে যদি পাইথন ২ এবং ৩ উভয়ই ইনস্টল করা থাকে, তবে এর পরিবর্তে আপনাকে pip2 ব্যবহার করতে হতে পারে।
  2. নিশ্চিত করুন যে আপনি gcloud কমান্ড-লাইন টুলটি ইনস্টলচালু করেছেন এবং এর ব্যবহারবিধি পর্যালোচনা করেছেন।
  3. (ঐচ্ছিক) যদি আপনি প্রতিটি gcloud কমান্ডের সাথে PROJECT_ID প্রবেশ করাতে না চান, তাহলে gcloud config set project PROJECT_ID ব্যবহার করে আপনার ক্লাউড প্রজেক্ট সেট করুন।
  4. gcloud app deploy ব্যবহার করে নমুনা অ্যাপটি ডিপ্লয় করুন।
  5. অ্যাপটি কোনো সমস্যা ছাড়াই প্রত্যাশিতভাবে চলছে কিনা তা নিশ্চিত করুন। আপনি যদি মডিউল ৮-এর কোডল্যাবটি সম্পন্ন করে থাকেন, তাহলে অ্যাপটি শীর্ষস্থানীয় ভিজিটরদের পাশাপাশি সাম্প্রতিকতম ভিজিটগুলোও প্রদর্শন করবে (নিচে চিত্রিত)। একদম নিচে পুরোনো টাস্কগুলোর একটি ইঙ্গিত থাকবে, যেগুলো মুছে ফেলা হবে।

4aa8a2cb5f527079.png

৪. কনফিগারেশন আপডেট করুন

requirements.txt

নতুন requirements.txt ফাইলটি মডিউল ৮-এর ফাইলের প্রায় অনুরূপ, শুধু একটি বড় পরিবর্তন রয়েছে: google-cloud-ndb এর পরিবর্তে google-cloud-datastore ব্যবহার করুন। এই পরিবর্তনটি করুন যাতে আপনার requirements.txt ফাইলটি দেখতে এইরকম হয়:

flask
google-cloud-datastore
google-cloud-tasks

এই requirements.txt ফাইলটিতে কোনো ভার্সন নম্বর নেই, যার মানে হলো সর্বশেষ ভার্সনগুলোই নির্বাচিত হয়েছে। যদি কোনো অসামঞ্জস্য দেখা দেয়, তবে কোনো অ্যাপের জন্য কার্যকরী ভার্সন নিশ্চিত করতে ভার্সন নম্বর ব্যবহার করা একটি প্রচলিত পদ্ধতি।

app.yaml

দ্বিতীয় প্রজন্মের অ্যাপ ইঞ্জিন রানটাইম ২.x-এর মতো বিল্ট-ইন থার্ড-পার্টি লাইব্রেরি সমর্থন করে না, এবং এটি নন -বিল্ট-ইন লাইব্রেরি কপি করাও সমর্থন করে না। থার্ড-পার্টি প্যাকেজের জন্য একমাত্র শর্ত হলো requirements.txt ফাইলে সেগুলোর তালিকা দেওয়া। ফলে, app.yaml ফাইলের libraries সেকশনটি সম্পূর্ণ মুছে ফেলা যেতে পারে।

আরেকটি আপডেট হলো যে, পাইথন ৩ রানটাইমের জন্য এমন ওয়েব ফ্রেমওয়ার্ক ব্যবহার করা প্রয়োজন যেগুলো নিজস্ব রাউটিং করে। ফলে, সমস্ত স্ক্রিপ্ট হ্যান্ডলারকে অবশ্যই auto তে পরিবর্তন করতে হবে। তবে, যেহেতু সমস্ত রাউটকে auto তে পরিবর্তন করতে হচ্ছে এবং এই স্যাম্পল অ্যাপ থেকে কোনো স্ট্যাটিক ফাইল সার্ভ করা হচ্ছে না, তাই কোনো হ্যান্ডলার থাকার প্রয়োজন নেই, সুতরাং সম্পূর্ণ handlers সেকশনটিও সরিয়ে ফেলুন।

app.yaml ফাইলে শুধু রানটাইমকে পাইথন ৩-এর একটি সমর্থিত সংস্করণে, যেমন ৩.১০-এ, সেট করতে হবে। এই পরিবর্তনটি করুন যাতে নতুন, সংক্ষিপ্ত app.yaml শুধু এই একটি লাইনই থাকে:

runtime: python310

appengine_config.py এবং lib মুছে ফেলুন

পরবর্তী প্রজন্মের অ্যাপ ইঞ্জিন রানটাইমগুলো থার্ড-পার্টি প্যাকেজ ব্যবহারের ক্ষেত্রে আমূল পরিবর্তন আনছে:

  • বিল্ট-ইন লাইব্রেরিগুলো হলো গুগল দ্বারা যাচাইকৃত এবং অ্যাপ ইঞ্জিন সার্ভারে উপলব্ধ করা লাইব্রেরি, সম্ভবত কারণ সেগুলোতে এমন C/C++ কোড থাকে যা ডেভেলপারদের ক্লাউডে স্থাপন করার অনুমতি নেই—এগুলো দ্বিতীয় প্রজন্মের রানটাইমগুলোতে আর পাওয়া যায় না।
  • দ্বিতীয় প্রজন্মের রানটাইমগুলোতে নন-বিল্ট-ইন লাইব্রেরি কপি করার (যাকে কখনও কখনও 'ভেন্ডরিং' বা 'সেলফ-বান্ডলিং' বলা হয়) আর প্রয়োজন নেই। এর পরিবর্তে, সেগুলোকে requirements.txt ফাইলে তালিকাভুক্ত করা উচিত, যেখানে বিল্ড সিস্টেম ডিপ্লয় করার সময় আপনার হয়ে স্বয়ংক্রিয়ভাবে সেগুলো ইনস্টল করে দেয়।

থার্ড-পার্টি প্যাকেজ ম্যানেজমেন্টে করা সেই পরিবর্তনগুলোর ফলে, appengine_config.py ফাইল বা lib ফোল্ডার কোনোটিরই আর প্রয়োজন নেই, তাই সেগুলো ডিলিট করে দিন। দ্বিতীয় প্রজন্মের রানটাইমগুলোতে, App Engine স্বয়ংক্রিয়ভাবে requirements.txt এ তালিকাভুক্ত থার্ড-পার্টি প্যাকেজগুলো ইনস্টল করে। সারসংক্ষেপ:

  1. আলাদাভাবে বান্ডেল করা বা কপি করা কোনো থার্ড-পার্টি লাইব্রেরি ব্যবহার করা যাবে না; সেগুলোর তালিকা requirements.txt ফাইলে দিন।
  2. lib ফোল্ডারে pip install যাবে না, অর্থাৎ lib ফোল্ডারই থাকবে না।
  3. app.yaml ফাইলে কোনো বিল্ট-ইন থার্ড-পার্টি লাইব্রেরির তালিকা নেই (তাই কোনো libraries সেকশনও নেই); সেগুলোকে requirements.txt ফাইলে তালিকাভুক্ত করুন।
  4. আপনার অ্যাপে কোনো থার্ড-পার্টি লাইব্রেরি রেফারেন্স করার প্রয়োজন না থাকায় appengine_config.py ফাইলেরও প্রয়োজন নেই।

requirements.txt ফাইলে প্রয়োজনীয় সমস্ত থার্ড-পার্টি লাইব্রেরির তালিকা করাই ডেভেলপারদের জন্য একমাত্র আবশ্যকতা।

৫. অ্যাপ্লিকেশন ফাইলগুলো আপডেট করুন

এখানে শুধুমাত্র একটিই অ্যাপ্লিকেশন ফাইল আছে, main.py , তাই এই অংশের সমস্ত পরিবর্তন শুধু সেই ফাইলটিকেই প্রভাবিত করবে। বিদ্যমান কোডটিকে নতুন অ্যাপে রিফ্যাক্টর করার জন্য যে সামগ্রিক পরিবর্তনগুলো করতে হবে, তার একটি "diffs" চিত্র নিচে দেওয়া হলো। পাঠকদের কোডটি লাইন-বাই-লাইন পড়ার প্রয়োজন নেই, কারণ এর উদ্দেশ্য হলো এই রিফ্যাক্টরে কী কী প্রয়োজন তার একটি সচিত্র ধারণা দেওয়া (তবে চাইলে নতুন ট্যাবে খুলতে বা ডাউনলোড করে জুম করতে পারেন)।

5d043768ba7be742.png

আমদানি এবং প্রারম্ভিকীকরণ আপডেট করুন

মডিউল ৮-এর জন্য main.py এর ইম্পোর্ট সেকশনে Cloud NDB এবং Cloud Tasks ব্যবহার করা হয়েছে; এটি দেখতে নিম্নরূপ হবে:

পূর্বে:

from datetime import datetime
import json
import logging
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, tasks

app = Flask(__name__)
ds_client = ndb.Client()
ts_client = tasks.CloudTasksClient()

পাইথন ৩-এর মতো দ্বিতীয় প্রজন্মের রানটাইমগুলিতে লগিং সরল ও উন্নত করা হয়েছে:

  • পূর্ণাঙ্গ লগিং অভিজ্ঞতার জন্য ক্লাউড লগিং ব্যবহার করুন।
  • সহজ লগিংয়ের জন্য, print() এর মাধ্যমে stdout (বা stderr )-এ পাঠিয়ে দিন।
  • পাইথন logging মডিউল ব্যবহার করার কোনো প্রয়োজন নেই (তাই এটি সরিয়ে দিন)।

সেই অনুযায়ী, logging এর ইম্পোর্টটি ডিলিট করুন এবং google.cloud.ndb এর পরিবর্তে google.cloud.datastore ব্যবহার করুন। একইভাবে, ds_client NDB ক্লায়েন্টের পরিবর্তে একটি Datastore ক্লায়েন্টের দিকে নির্দেশ করার জন্য পরিবর্তন করুন। এই পরিবর্তনগুলো করার পর, আপনার নতুন অ্যাপের উপরের অংশটি এখন দেখতে এইরকম হবে:

পরে:

from datetime import datetime
import json
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import datastore, tasks

app = Flask(__name__)
ds_client = datastore.Client()
ts_client = tasks.CloudTasksClient()

ক্লাউড ডেটাস্টোরে স্থানান্তরিত করুন

এখন NDB ক্লায়েন্ট লাইব্রেরির ব্যবহার ডেটাস্টোর দিয়ে প্রতিস্থাপন করার সময় এসেছে। অ্যাপ ইঞ্জিন NDB এবং ক্লাউড NDB উভয়ের জন্যই একটি ডেটা মডেল (ক্লাস) প্রয়োজন; এই অ্যাপটির জন্য, সেটি হলো Visit '। store_visit() ফাংশনটি অন্য সব মাইগ্রেশন মডিউলে একইভাবে কাজ করে: এটি একটি নতুন Visit রেকর্ড তৈরি করে এবং ভিজিটিং ক্লায়েন্টের আইপি অ্যাড্রেস ও ইউজার এজেন্ট (ব্রাউজারের ধরন) সংরক্ষণ করে একটি ভিজিট রেজিস্টার করে।

পূর্বে:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

তবে ক্লাউড ডেটাস্টোর কোনো ডেটা মডেল ক্লাস ব্যবহার করে না , তাই ক্লাসটি ডিলিট করে দিন। এছাড়াও, রেকর্ড তৈরি করার সময় ক্লাউড ডেটাস্টোর স্বয়ংক্রিয়ভাবে টাইমস্ট্যাম্প তৈরি করে না, ফলে আপনাকে এটি ম্যানুয়ালি করতে হয়—এই কাজটি datetime.now() কলের মাধ্যমে করা হয়।

ডেটা ক্লাস ছাড়া, আপনার পরিবর্তিত store_visit() দেখতে এইরকম হবে:

পরে:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    entity = datastore.Entity(key=ds_client.key('Visit'))
    entity.update({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })
    ds_client.put(entity)

মূল ফাংশনটি হলো fetch_visits() । এটি শুধু সর্বশেষ Visit জন্য মূল কোয়েরিটিই চালায় না, বরং প্রদর্শিত সর্বশেষ Visit টাইমস্ট্যাম্পও সংগ্রহ করে এবং একটি পুশ টাস্ক তৈরি করে যা পুরোনো Visit একসাথে মুছে ফেলার জন্য /trim (অর্থাৎ trim() ) কল করে। নিচে ক্লাউড এনডিবি ব্যবহার করে এটি দেখানো হলো:

পূর্বে:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    with ds_client.context():
        data = Visit.query().order(-Visit.timestamp).fetch(limit)
    oldest = time.mktime(data[-1].timestamp.timetuple())
    oldest_str = time.ctime(oldest)
    logging.info('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return (v.to_dict() for v in data), oldest_str

প্রধান পরিবর্তনগুলো হলো:

  1. ক্লাউড এনডিবি কোয়েরিটি ক্লাউড ডেটাস্টোরের সমতুল্য কোয়েরি দিয়ে পরিবর্তন করুন; কোয়েরির ধরণ সামান্য ভিন্ন।
  2. ক্লাউড এনডিবি-র মতো ডেটাস্টোর ব্যবহারের জন্য কোনো কনটেক্সট ম্যানেজারের প্রয়োজন হয় না, কিংবা এটি আপনাকে to_dict() ফাংশনের মাধ্যমে এর ডেটা এক্সট্র্যাক্ট করতেও বাধ্য করে না।
  3. লগিং কলগুলোকে print() দিয়ে প্রতিস্থাপন করুন।

এই পরিবর্তনগুলোর পর, fetch_visits() দেখতে এইরকম হবে:

পরে:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

সাধারণত এটুকুই যথেষ্ট। দুর্ভাগ্যবশত, একটি বড় সমস্যা আছে।

(সম্ভবত) একটি নতুন (পুশ) কিউ তৈরি করুন

মডিউল ৭-এ, আমরা বিদ্যমান মডিউল ১ অ্যাপে অ্যাপ ইঞ্জিন taskqueue ব্যবহারের সুবিধা যুক্ত করেছি। অ্যাপ ইঞ্জিনের একটি লিগ্যাসি ফিচার হিসেবে পুশ টাস্ক থাকার একটি প্রধান সুবিধা হলো, একটি "ডিফল্ট" কিউ স্বয়ংক্রিয়ভাবে তৈরি হয়ে যায়। যখন মডিউল ৮-এ অ্যাপটিকে ক্লাউড টাস্কসে মাইগ্রেট করা হয়েছিল, তখন সেই ডিফল্ট কিউটি আগে থেকেই ছিল, তাই তখনও আমাদের এটি নিয়ে চিন্তা করার প্রয়োজন পড়েনি। মডিউল ৯-এ এসে সেই অবস্থার পরিবর্তন হচ্ছে।

একটি গুরুত্বপূর্ণ বিষয় হলো, নতুন অ্যাপ ইঞ্জিন অ্যাপ্লিকেশনটি আর অ্যাপ ইঞ্জিন সার্ভিস ব্যবহার করে না। ফলে, আপনি আর ধরে নিতে পারবেন না যে অ্যাপ ইঞ্জিন স্বয়ংক্রিয়ভাবে অন্য কোনো প্রোডাক্টে (ক্লাউড টাস্কস) একটি টাস্ক কিউ তৈরি করবে। যেভাবে লেখা আছে, তাতে fetch_visits() ফাংশনে (একটি অস্তিত্বহীন কিউ-এর জন্য) টাস্ক তৈরি করার চেষ্টা ব্যর্থ হবে। একটি নতুন ফাংশন প্রয়োজন, যা পরীক্ষা করে দেখবে ("ডিফল্ট") কিউ-টি আছে কি না, এবং না থাকলে একটি তৈরি করবে।

এই ফাংশনটির নাম _create_queue_if() দিন এবং এটিকে আপনার অ্যাপ্লিকেশনে fetch_visits() ফাংশনের ঠিক উপরে যোগ করুন, কারণ এটি সেখানেই কল করা হয়। যে ফাংশন বডিটি যোগ করতে হবে তা হলো:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

Cloud Tasks-এর create_queue() ফাংশনটির জন্য কিউ-এর নাম ছাড়া এর সম্পূর্ণ পাথনেম প্রয়োজন হয়। সরলতার জন্য, QUEUE_PATH থেকে কিউ-এর নাম বাদ দিয়ে PATH_PREFIX নামে আরেকটি ভ্যারিয়েবল তৈরি করুন ( QUEUE_PATH.rsplit('/', 2)[0] )। এর ডেফিনিশনটি কোডের উপরের দিকে যোগ করুন, যাতে সমস্ত কনস্ট্যান্ট অ্যাসাইনমেন্ট সহ কোড ব্লকটি দেখতে এইরকম হয়:

_, PROJECT_ID = google.auth.default()
REGION_ID = 'REGION_ID'    # replace w/your own
QUEUE_NAME = 'default'     # replace w/your own
QUEUE_PATH = ts_client.queue_path(PROJECT_ID, REGION_ID, QUEUE_NAME)
PATH_PREFIX = QUEUE_PATH.rsplit('/', 2)[0]

এখন fetch_visits() ফাংশনের শেষ লাইনটি পরিবর্তন করে _create_queue_if() ব্যবহার করুন, প্রথমে প্রয়োজন হলে কিউ তৈরি করুন, তারপরে টাস্কটি তৈরি করুন:

    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

_create_queue_if() এবং fetch_visits() উভয়ই এখন সামগ্রিকভাবে দেখতে এইরকম হবে:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

এই অতিরিক্ত কোডটি যোগ করা ছাড়া, ক্লাউড টাস্কের বাকি কোডটি মডিউল ৮ থেকে প্রায় অক্ষত রয়েছে। সবশেষে যে কোডটি দেখতে হবে তা হলো টাস্ক হ্যান্ডলার।

আপডেট (পুশ) টাস্ক হ্যান্ডলার

টাস্ক হ্যান্ডলার trim() এ, ক্লাউড এনডিবি কোডটি প্রদর্শিত সবচেয়ে পুরানো ভিজিটের চেয়েও পুরানো ভিজিটগুলোর জন্য কোয়েরি করে। এটি গতি বাড়ানোর জন্য একটি 'কী-অনলি' কোয়েরি ব্যবহার করে—যদি আপনার শুধু ভিজিট আইডিগুলোর প্রয়োজন হয়, তবে সমস্ত ডেটা আনার দরকার কী? একবার সমস্ত ভিজিট আইডি পেয়ে গেলে, ক্লাউড এনডিবি-র delete_multi() ফাংশন ব্যবহার করে সেগুলোকে একসাথে ব্যাচ আকারে ডিলিট করে দিন।

পূর্বে:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = float(request.get_json().get('oldest'))
    with ds_client.context():
        keys = Visit.query(
                Visit.timestamp < datetime.fromtimestamp(oldest)
        ).fetch(keys_only=True)
        nkeys = len(keys)
        if nkeys:
            logging.info('Deleting %d entities: %s' % (
                    nkeys, ', '.join(str(k.id()) for k in keys)))
            ndb.delete_multi(keys)
        else:
            logging.info(
                    'No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

fetch_visits() মতোই, বেশিরভাগ পরিবর্তনগুলোর মধ্যে রয়েছে Cloud NDB কোডের পরিবর্তে Cloud Datastore ব্যবহার করা, কোয়েরি স্টাইলগুলোতে সামান্য পরিবর্তন আনা, এর কনটেক্সট ম্যানেজারের ব্যবহার বাদ দেওয়া এবং লগিং কলগুলোকে print() এ পরিবর্তন করা।

পরে:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = float(request.get_json().get('oldest'))
    query = ds_client.query(kind='Visit')
    query.add_filter('timestamp', '<', datetime.fromtimestamp(oldest))
    query.keys_only()
    keys = list(visit.key for visit in query.fetch())
    nkeys = len(keys)
    if nkeys:
        print('Deleting %d entities: %s' % (
                nkeys, ', '.join(str(k.id) for k in keys)))
        ds_client.delete_multi(keys)
    else:
        print('No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

মূল অ্যাপ্লিকেশন হ্যান্ডলার root() এ কোনো পরিবর্তন নেই।

পাইথন ৩-এ পোর্ট করুন

এই নমুনা অ্যাপটি পাইথন ২ এবং ৩ উভয়টিতেই চলার জন্য ডিজাইন করা হয়েছে। পাইথন ৩-এর জন্য নির্দিষ্ট কোনো পরিবর্তন থাকলে, তা এই টিউটোরিয়ালের প্রাসঙ্গিক অংশগুলোতে আগেই আলোচনা করা হয়েছে। এর জন্য কোনো অতিরিক্ত ধাপ বা কম্প্যাটিবিলিটি লাইব্রেরির প্রয়োজন নেই।

ক্লাউড টাস্ক আপডেট

পাইথন ২ সমর্থনকারী ক্লাউড টাস্কস ক্লায়েন্ট লাইব্রেরির সর্বশেষ সংস্করণটি হলো ১.৫.০। এই লেখাটি লেখার সময়, পাইথন ৩-এর জন্য ক্লায়েন্ট লাইব্রেরির সর্বশেষ সংস্করণটি সেই সংস্করণের সাথে সম্পূর্ণরূপে সামঞ্জস্যপূর্ণ, সুতরাং আর কোনো আপডেটের প্রয়োজন নেই।

এইচটিএমএল টেমপ্লেট আপডেট

HTML টেমপ্লেট ফাইল, templates/index.html এও কোনো পরিবর্তনের প্রয়োজন নেই, সুতরাং মডিউল ৯ অ্যাপটি তৈরি করার জন্য প্রয়োজনীয় সমস্ত পরিবর্তন এখানেই শেষ।

৬. সারসংক্ষেপ/পরিষ্কারকরণ

অ্যাপ্লিকেশনটি স্থাপন এবং যাচাই করুন

কোড আপডেট, বিশেষ করে পাইথন ৩-এ পোর্ট করার কাজ শেষ হয়ে গেলে, gcloud app deploy দিয়ে আপনার অ্যাপটি ডিপ্লয় করুন। আউটপুটটি মডিউল ৭ এবং ৮-এর অ্যাপগুলোর মতোই হওয়া উচিত, তবে পার্থক্য হলো আপনি ডাটাবেস অ্যাক্সেসটি ক্লাউড ডেটাস্টোর ক্লায়েন্ট লাইব্রেরিতে স্থানান্তর করেছেন এবং পাইথন ৩-এ আপগ্রেড করেছেন।

মডিউল ৭ ভিজিটমি অ্যাপ

এই ধাপে কোডল্যাব সম্পন্ন হলো। মডিউল ৯ ফোল্ডারে থাকা কোডের সাথে আপনার কোডটি তুলনা করে দেখুন। অভিনন্দন!

পরিষ্কার করা

সাধারণ

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

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

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • উপরের স্টোরেজ লিঙ্কগুলি আপনার PROJECT_ID এবং * LOC *-এর উপর নির্ভর করে, উদাহরণস্বরূপ, " us " যদি আপনার অ্যাপটি মার্কিন যুক্তরাষ্ট্রে হোস্ট করা হয়।

অন্যদিকে, যদি আপনি এই অ্যাপ্লিকেশন বা অন্যান্য সম্পর্কিত মাইগ্রেশন কোডল্যাবগুলো নিয়ে আর কাজ চালিয়ে যেতে না চান এবং সবকিছু পুরোপুরি মুছে ফেলতে চান, তাহলে আপনার প্রজেক্টটি শাট ডাউন করুন

এই কোডল্যাবের জন্য নির্দিষ্ট

নীচে তালিকাভুক্ত পরিষেবাগুলি এই কোডল্যাবের জন্য অনন্য। আরও তথ্যের জন্য প্রতিটি পণ্যের ডকুমেন্টেশন দেখুন:

পরবর্তী পদক্ষেপ

এর মাধ্যমে অ্যাপ ইঞ্জিন টাস্ক কিউ পুশ টাস্ক থেকে ক্লাউড টাস্কে আমাদের মাইগ্রেশন সম্পন্ন হলো। ক্লাউড এনডিবি থেকে ক্লাউড ডেটাস্টোরে ঐচ্ছিক মাইগ্রেশনটিও (টাস্ক কিউ বা ক্লাউড টাস্ক ছাড়া) মডিউল ৩- এ আলাদাভাবে আলোচনা করা হয়েছে। মডিউল ৩ ছাড়াও, অ্যাপ ইঞ্জিনের লিগ্যাসি বান্ডেলড সার্ভিসগুলো থেকে সরে আসার উপর আলোকপাতকারী আরও কিছু মাইগ্রেশন মডিউল রয়েছে যা বিবেচনা করা যেতে পারে, যেমন:

  • মডিউল ২ : অ্যাপ ইঞ্জিন এনডিবি থেকে ক্লাউড এনডিবি-তে স্থানান্তর
  • মডিউল ৩ : ক্লাউড এনডিবি থেকে ক্লাউড ডেটাস্টোরে স্থানান্তর
  • মডিউল ১২-১৩ : অ্যাপ ইঞ্জিন মেমক্যাশ থেকে ক্লাউড মেমোরিস্টোরে স্থানান্তর
  • মডিউল ১৫-১৬ : অ্যাপ ইঞ্জিন ব্লবস্টোর থেকে ক্লাউড স্টোরেজে স্থানান্তর
  • মডিউল ১৮-১৯ : অ্যাপ ইঞ্জিন টাস্ক কিউ (টাস্ক পুল করা) থেকে ক্লাউড পাব/সাব-এ

গুগল ক্লাউডে অ্যাপ ইঞ্জিন এখন আর একমাত্র সার্ভারলেস প্ল্যাটফর্ম নয়। যদি আপনার একটি ছোট বা সীমিত কার্যকারিতাসম্পন্ন অ্যাপ ইঞ্জিন অ্যাপ থাকে এবং আপনি সেটিকে একটি স্বতন্ত্র মাইক্রোসার্ভিসে পরিণত করতে চান, অথবা একটি মনোলিথিক অ্যাপকে একাধিক পুনঃব্যবহারযোগ্য কম্পোনেন্টে বিভক্ত করতে চান, তবে ক্লাউড ফাংশনস -এ স্থানান্তরিত হওয়ার কথা বিবেচনা করার জন্য এগুলোই যথেষ্ট কারণ। যদি কন্টেইনারাইজেশন আপনার অ্যাপ্লিকেশন ডেভেলপমেন্ট ওয়ার্কফ্লোর একটি অংশ হয়ে থাকে, বিশেষ করে যদি এতে একটি CI/CD (কন্টিনিউয়াস ইন্টিগ্রেশন/কন্টিনিউয়াস ডেলিভারি বা ডিপ্লয়মেন্ট) পাইপলাইন থাকে, তবে ক্লাউড রান -এ মাইগ্রেট করার কথা বিবেচনা করুন। এই পরিস্থিতিগুলো নিম্নলিখিত মডিউলগুলোর আওতায় পড়ে:

  • অ্যাপ ইঞ্জিন থেকে ক্লাউড ফাংশনে স্থানান্তর করুন: মডিউল ১১ দেখুন।
  • অ্যাপ ইঞ্জিন থেকে ক্লাউড রান-এ মাইগ্রেট করুন: ডকার ব্যবহার করে আপনার অ্যাপকে কন্টেইনারাইজ করতে মডিউল ৪ দেখুন, অথবা কন্টেইনার, ডকার জ্ঞান বা Dockerfile ছাড়াই এটি করতে মডিউল ৫ দেখুন।

অন্য কোনো সার্ভারলেস প্ল্যাটফর্মে পরিবর্তন করা ঐচ্ছিক, এবং আমরা সুপারিশ করি যে কোনো পরিবর্তন করার আগে আপনার অ্যাপ ও ব্যবহারের ক্ষেত্রগুলোর জন্য সেরা বিকল্পগুলো বিবেচনা করে নিন।

এরপরে আপনি যে মাইগ্রেশন মডিউলটিই বিবেচনা করুন না কেন, সার্ভারলেস মাইগ্রেশন স্টেশনের সমস্ত কন্টেন্ট (কোডল্যাব, ভিডিও, সোর্স কোড [যখন উপলব্ধ]) এর ওপেন সোর্স রিপো থেকে অ্যাক্সেস করা যাবে। রিপোটির README কোন মাইগ্রেশনগুলো বিবেচনা করা উচিত এবং মাইগ্রেশন মডিউলগুলোর প্রাসঙ্গিক "ক্রম" সম্পর্কেও নির্দেশনা দেওয়া আছে।

৭. অতিরিক্ত সম্পদ

কোডল্যাবস সমস্যা/মতামত

এই কোডল্যাবে কোনো সমস্যা পেলে, অভিযোগ জানানোর আগে অনুগ্রহ করে সমস্যাটি অনুসন্ধান করুন। নতুন সমস্যা অনুসন্ধান ও তৈরি করার লিঙ্ক:

অভিবাসন সম্পদ

মডিউল ৮ (শুরু) এবং মডিউল ৯ (শেষ)-এর রিপো ফোল্ডারগুলোর লিঙ্ক নিচের টেবিলে দেওয়া আছে। এছাড়াও, সমস্ত অ্যাপ ইঞ্জিন কোডল্যাব মাইগ্রেশনের রিপো থেকেও এগুলো অ্যাক্সেস করা যাবে, যা আপনি ক্লোন করতে পারেন অথবা একটি জিপ ফাইল হিসেবে ডাউনলোড করতে পারেন।

কোডল্যাব

পাইথন ২

পাইথন ৩

মডিউল ৮

কোড

(প্রযোজ্য নয়)

মডিউল ৯

(প্রযোজ্য নয়)

কোড

অনলাইন রিসোর্স

এই টিউটোরিয়ালটির জন্য প্রাসঙ্গিক হতে পারে এমন কিছু অনলাইন রিসোর্স নিচে দেওয়া হলো:

অ্যাপ ইঞ্জিন

ক্লাউড এনডিবি

ক্লাউড ডেটাস্টোর

ক্লাউড টাস্ক

অন্যান্য ক্লাউড তথ্য

লাইসেন্স

এই কাজটি ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন ২.০ জেনেরিক লাইসেন্সের অধীনে রয়েছে।