paint-brush
FastAPI-তে রিপোজিটরি প্যাটার্ন ব্যবহার করে দক্ষ সেশন হ্যান্ডলিংদ্বারা@abram
5,579 পড়া
5,579 পড়া

FastAPI-তে রিপোজিটরি প্যাটার্ন ব্যবহার করে দক্ষ সেশন হ্যান্ডলিং

দ্বারা Abram9m2023/06/09
Read on Terminal Reader
Read this story w/o Javascript

অতিদীর্ঘ; পড়তে

ডেটা সামঞ্জস্য বজায় রাখতে, ত্রুটি প্রতিরোধ করতে এবং ব্যাকএন্ড সিস্টেমের স্থিতিশীলতা নিশ্চিত করার জন্য দক্ষ সেশন পরিচালনা অত্যন্ত গুরুত্বপূর্ণ। প্রসঙ্গ পরিচালকদের ব্যবহার এবং সংগ্রহস্থলের প্যাটার্ন গ্রহণ করার মতো সেরা অনুশীলনগুলি অনুসরণ করে, বিকাশকারীরা শক্তিশালী এবং নির্ভরযোগ্য সিস্টেম তৈরি করতে পারে যা কার্যকরভাবে সেশনগুলি পরিচালনা করে এবং ডাটাবেস লেনদেনের সময় ত্রুটিগুলি পরিচালনা করে।
featured image - FastAPI-তে রিপোজিটরি প্যাটার্ন ব্যবহার করে দক্ষ সেশন হ্যান্ডলিং
Abram HackerNoon profile picture

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


আমি সরাসরি এটিতে ঝাঁপিয়ে পড়ার আগে, আমি লক্ষ্য করেছি যে প্রোডাকশনে, যখনই আমার API গুলি ডাটাবেসে পড়া বা লেখার সাথে জড়িত এমন একটি লেনদেন করার চেষ্টা করে তখন আমি নিম্নলিখিত ত্রুটিগুলি পাই:


  • sqlalchemy.exc.PendingRollbackError
  • sqlalchemy.exc.InvalidRequestError

sqlalchemy.exc.PendingRollbackError

এই ত্রুটিটি ইঙ্গিত করে যে একটি অনিয়মিত লেনদেন চলছে যা অন্য কোনো ডাটাবেস ক্রিয়াকলাপের সাথে এগিয়ে যাওয়ার আগে রোলব্যাক করা দরকার।


এই ত্রুটির সবচেয়ে সাধারণ কারণ হল একটি ডাটাবেস লেনদেনের সময় একটি আন-হ্যান্ডেল করা ব্যতিক্রম, যা লেনদেনকে প্রতিশ্রুতিবদ্ধ বা সঠিকভাবে রোল ব্যাক করা থেকে বাধা দেয়।

sqlalchemy.exc.InvalidRequestError

এই ত্রুটিটি নির্দেশ করে যে একটি অপারেশন বা অনুরোধ যা আপনি ডাটাবেসে করেছেন তা অবৈধ বা সমর্থিত নয়। এই ত্রুটির জন্য বিভিন্ন কারণ থাকতে পারে, যার মধ্যে রয়েছে:


  • SQLAlchemy API-এর ভুল ব্যবহার, যেমন একটি মেথড কল করা বা কোনো অ্যাট্রিবিউট অ্যাক্সেস করা যা বিদ্যমান নেই বা প্রদত্ত প্রসঙ্গে প্রযোজ্য নয়।


  • ভুল SQL সিনট্যাক্স বা ক্যোয়ারী গঠন.


  • পাইথন অবজেক্ট এবং ডাটাবেস টেবিল/কলামের মধ্যে অনুপস্থিত বা ভুল ম্যাপিং।


আমি নিশ্চিত যে এই ত্রুটিগুলি কীভাবে সমাধান করা যেতে পারে সে সম্পর্কে আপনার চিন্তাভাবনা আছে, তবে, আমি বলতে চাই যে যদিও আমি সমস্যাটি চিহ্নিত করেছি এবং একটি সমাধান করেছি- সমস্যাটি রয়ে গেছে৷


আমি কীভাবে সমস্যা সমাধান এবং সমাধান করব সে সম্পর্কে আপনি যদি আগ্রহী হন তবে আপনি নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করতে পারেন:

sqlalchemy.exc.PendingRollbackError:

  • লেনদেনগুলিকে প্রতিশ্রুতিবদ্ধ হতে বা সঠিকভাবে রোল ব্যাক করা থেকে আটকাতে পারে এমন কোনও অ-হ্যান্ডেল করা ব্যতিক্রমগুলির জন্য আপনার কোডটি পর্যালোচনা করুন৷ নিশ্চিত করুন যে আপনি সঠিকভাবে ব্যতিক্রমগুলি পরিচালনা করছেন এবং প্রয়োজন অনুসারে লেনদেনটি কমিট বা রোল ব্যাক করছেন।


  • মুলতুবি রোলব্যাক হতে পারে এমন কোনো দীর্ঘ-চলমান বা নেস্টেড লেনদেনের জন্য পরীক্ষা করুন। নিশ্চিত করুন যে সমস্ত লেনদেন একটি সময়মত পদ্ধতিতে প্রতিশ্রুতিবদ্ধ বা ফিরিয়ে আনা হয়েছে৷


  • আগের লেনদেন সঠিকভাবে পরিচালনা করার আগে আপনি একটি নতুন লেনদেন শুরু করতে পারেন এমন যেকোনো ক্ষেত্রে আপনার কোড পর্যালোচনা করুন।

sqlalchemy.exc.InvalidRequestError:

  • অবৈধ অনুরোধের কারণ সনাক্ত করতে ব্যতিক্রম সহ প্রদত্ত নির্দিষ্ট ত্রুটি বার্তাটি পর্যালোচনা করুন। এটি আপনাকে আপনার কোড বা SQL স্টেটমেন্টের কোন অংশে সমস্যা সৃষ্টি করছে সে সম্পর্কে ইঙ্গিত দিতে পারে।


  • কোনো ভুল পদ্ধতি কল, অ্যাট্রিবিউট অ্যাক্সেস, বা API এর ভুল ব্যবহারের জন্য আপনার SQLAlchemy কোড পরীক্ষা করুন।


  • আপনার এসকিউএল স্টেটমেন্টগুলি সঠিক সিনট্যাক্স এবং কাঠামো আছে তা নিশ্চিত করতে পর্যালোচনা করুন।


  • আপনার ডাটাবেস স্কিমা এবং SQLAlchemy ম্যাপিংগুলি সিঙ্কে রয়েছে তা যাচাই করুন৷ নিশ্চিত করুন যে সমস্ত প্রয়োজনীয় টেবিল এবং কলাম বিদ্যমান এবং আপনার পাইথন বস্তুগুলি সংশ্লিষ্ট ডাটাবেস সত্তাগুলিতে সঠিকভাবে ম্যাপ করা হয়েছে।


আসুন আমি কীভাবে একটি স্থায়ী সমাধানে কাজ করেছি যা আমার জন্য কাজ করতে প্রমাণিত হয়েছে তা সরাসরি জেনে নেওয়া যাক। আমি এমন একটি প্রকল্প ব্যবহার করতে এগিয়ে যাবো যেটিতে আমি কাজ করেছি যখন আমি প্রদর্শন করছিলাম কিভাবে সংগ্রহস্থলের নিদর্শন ব্যবহার করতে হয়।


আমাদের একটি মডিউল ছিল যেখানে আমরা নিম্নলিখিত কোডগুলির সাথে আমাদের orm বেস সেশন মিক্সিন সংরক্ষণ করেছি:


 # SQLAlchemy Imports from sqlalchemy.orm import Session # Own Imports from config.database import SessionLocal from core.settings import ledger_settings class ORMSessionMixin: """Base orm session mixin for interacting with the database.""" def __init__(self): """ Get the next database session from the database pool. """ self.orm: Session = self.get_db().__next__() def get_db(self): """ This method creates a database session, yields it, rollback the transaction if there's an exception and then finally closes the session. Yields: db: scoped database session """ db = SessionLocal() try: yield db except Exception: db.rollback() finally: db.close()


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


তিন মাস ডিবাগিং এবং প্যাচিং এবং প্রচুর গবেষণার পরে, আমি অবশেষে সেশন পরিচালনা করার একটি কার্যকর উপায় তৈরি করতে সক্ষম হয়েছি।


 # SQLAlchemy Imports import sqlalchemy from sqlalchemy.orm import Session # Own Imports from config.database.connection import SessionLocal class DatabaseSessionMixin: """Database session mixin.""" def __enter__(self) -> Session: self.db = SessionLocal() return self.db def __exit__(self, exc_type, exc_val, exc_tb): try: if exc_type is not None: self.db.rollback() except sqlalchemy.exc.SQLAlchemyError: pass finally: self.db.close() SessionLocal.remove() def use_database_session(): return DatabaseSessionMixin()


এই কোডে:


  • DatabaseSession হল একটি কনটেক্সট ম্যানেজার ক্লাস যা সেশন পরিচালনা করে এবং নিশ্চিত করে যে এটি সঠিকভাবে বন্ধ করা হয়েছে এবং ত্রুটির ক্ষেত্রে রোল ব্যাক করা হয়েছে।


  • __enter__ পদ্ধতি সেশন শুরু করে এবং এটি ফেরত দেয়।


  • __exit__ পদ্ধতি ব্যতিক্রমগুলির জন্য পরীক্ষা করে এবং একটি ব্যতিক্রম ঘটলে সেশনটি রোল ব্যাক করে। এটি তারপর সেশনটি বন্ধ করে এবং স্কোপড সেশন থেকে সরিয়ে দেয়।


  • use_database_session হল একটি ইউটিলিটি ফাংশন যা সেশনের ব্যবহারকে সহজ করার জন্য ডেকোরেটর বা কনটেক্সট ম্যানেজার হিসাবে ব্যবহার করা যেতে পারে।


আপনি কিভাবে use_database_session ইউটিলিটি ফাংশন ব্যবহার করতে পারেন তার একটি উদাহরণ এখানে দেওয়া হল:


 with use_database_session() as db: # perform logic that uses the session # ... # After exiting the context, the session will be automatically closed and removed from the scoped session.


উপরের পদ্ধতিটি সেশনগুলি পরিচালনা করার জন্য একটি পরিষ্কার এবং আরও কার্যকর উপায় সরবরাহ করে এবং নিশ্চিত করে যে সেগুলি সঠিকভাবে ফিরিয়ে আনা হয়েছে বা কোনও ত্রুটির ক্ষেত্রে বন্ধ করা হয়েছে। ORM-এ ডাটাবেস সেশন ব্যবহার করার সময় আপনি কীভাবে রিপোজিটরি প্যাটার্ন বাস্তবায়ন করবেন সেদিকে এগিয়ে যাওয়া যাক।


 # SQLAlchemy Imports import sqlalchemy from sqlalchemy.orm import Session class BaseRepository: def __init__(self, session: Session): self.db = session class UserRepository(BaseRepository): """Operations to interact with the `users` table in the database.""" def get(self, user_id: int) -> User: """This method gets a user from the database.""" user = ( self.db.query(User) .filter(User.id == user_id) .first() ) return user def create(self, name: str, email: str, password: str) -> User: """This method creates a user.""" user = User(name=name, email=email, password=password) self.db.add(user) self.db.commit() self.db.refresh(user) return user def update_user(self, user_id: int, updated_data: dict): """This method updates a user.""" user = self.get(user_id) if user: for key, value in updated_data.items(): setattr(user, key, value) self.db.commit() return user return None def delete_user(self, user_id): """This method deletes a user.""" user = self.get_user(user_id) if user: self.db.delete(user) self.db.commit() return True return False


পরবর্তীটি আপনার অ্যাপ্লিকেশনের পরিষেবা স্তরে উপরের সংগ্রহস্থলকে একীভূত করতে হবে। ধরুন আপনার একটি পরিষেবা ফাংশন আছে যা ব্যবহারকারীদের অ্যাকাউন্ট তৈরি করে; আমাদের নতুন পদ্ধতি ব্যবহার করে আপনি এটি কীভাবে করবেন তা এখানে:


 # Apps Imports from apps.users.models import User from apps.users.repo import UserRepository from apps.users.schemas.auth import UserCreate # Config Imports from config.security.hashers import password from config.database.session_mixin import use_database_session async def create_user(user: UserCreate) -> User: """ This function creates a new user in the database. :param user: schemas.UserCreate :type user: schemas.UserCreate :return: The user object """ with use_database_session() as db: users_repo = UserRepository(db) user = users_repo.create( user.name, user.email, password.hash(user.password) ) return user


উপরের প্যাটার্নটি আপনাকে উত্তরাধিকারসূত্রে পাওয়া ডাটাবেস সেশনের সুবিধা দেওয়ার সময় সংগ্রহস্থলের ক্লাসের মধ্যে ডাটাবেস ক্রিয়াকলাপগুলিকে এনক্যাপসুলেট করার অনুমতি দেবে। এটি আপনার ORM মডেল এবং রিপোজিটরি লজিকের মধ্যে একটি পরিষ্কার বিচ্ছেদও প্রদান করে।

উপসংহার

উপসংহারে, ব্যাকএন্ড সিস্টেম তৈরি করার সময় সেশনগুলির দক্ষ পরিচালনা গুরুত্বপূর্ণ।


ডাটাবেস লেনদেনের সময় sqlalchemy.exc.PendingRollbackError এবং sqlalchemy.exc.InvalidRequestError এর মতো ত্রুটিগুলি সঠিকভাবে পরিচালনা না করলে ডেটা অসঙ্গতি এবং অ্যাপ্লিকেশন ব্যর্থতার কারণ হতে পারে।


সিস্টেমের অখণ্ডতা এবং নির্ভরযোগ্যতা বজায় রাখার জন্য এই ত্রুটিগুলি সনাক্ত করা এবং সমাধান করা গুরুত্বপূর্ণ।


অধিবেশন পরিচালনার সাথে সম্পর্কিত সমস্যাগুলি সমাধানের জন্য, শক্তিশালী কৌশলগুলি বাস্তবায়ন করা অপরিহার্য। একটি পদ্ধতি হল প্রসঙ্গ পরিচালকদের ব্যবহার করা, যেমন DatabaseSessionMixin আমরা নিবন্ধে দেখিয়েছি।


এই কনটেক্সট ম্যানেজার নিশ্চিত করে যে সেশনগুলি সঠিকভাবে খোলা, বন্ধ এবং ব্যতিক্রমের ক্ষেত্রে রোল ব্যাক করা হয়েছে। কনটেক্সট ম্যানেজারের মধ্যে সেশন লজিক এনক্যাপসুলেট করে, আপনি সেশন ম্যানেজমেন্টকে স্ট্রীমলাইন করতে পারেন এবং ত্রুটি পরিচালনার উন্নতি করতে পারেন।


উপরন্তু, অ্যাপ্লিকেশনের পরিষেবা স্তরে সংগ্রহস্থলের প্যাটার্নকে একীভূত করা সেশন পরিচালনার দক্ষতাকে আরও বাড়িয়ে তুলতে পারে।


ডাটাবেস ক্রিয়াকলাপগুলিকে রিপোজিটরি ক্লাসে আলাদা করে এবং কনটেক্সট ম্যানেজার থেকে উত্তরাধিকারসূত্রে প্রাপ্ত সেশনটি ব্যবহার করে, আপনি ক্লিনার কোড সংগঠন অর্জন করতে পারেন এবং ORM মডেল এবং রিপোজিটরি লজিকের মধ্যে একটি স্পষ্ট বিচ্ছেদ বজায় রাখতে পারেন।


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


সেরা অনুশীলনগুলি অনুসরণ করে, যেমন প্রসঙ্গ পরিচালকদের ব্যবহার করে এবং সংগ্রহস্থলের প্যাটার্ন গ্রহণ করে, বিকাশকারীরা শক্তিশালী এবং নির্ভরযোগ্য সিস্টেম তৈরি করতে পারে যা কার্যকরভাবে সেশনগুলি পরিচালনা করে এবং ডাটাবেস লেনদেনের সময় ত্রুটিগুলি পরিচালনা করে।


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