পাঠ ৫৪ · ৫৭-এর মধ্যে · মডিউল ১২
Home / Courses / Mobile App Development / রিলিজ প্রসেস

অ্যাপ স্টোর ও প্লে স্টোর রিলিজ প্রসেস

App Store & Play Store release process
৮ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • App Store ও Play Store-এর রিভিউ প্রক্রিয়ার মূল পার্থক্য — ম্যানুয়াল বনাম স্বয়ংক্রিয়
  • স্টেজড/পার্সেন্টেজ রোলআউট ও ফেজড রিলিজের ধারণা এবং এটি কেন ব্যবহার করা হয়
  • একটি নির্দিষ্ট রোলআউট শিডিউলের প্রতিটি ধাপে বাস্তবে কতজন ব্যবহারকারী নতুন সংস্করণে থাকে তা প্রকৃত অ্যারিথমেটিক দিয়ে হিসাব করা
  • একটি ক্র্যাশ-রেট মেট্রিকের ভিত্তিতে রোলব্যাক সিদ্ধান্ত কীভাবে সত্যিকারের কোডে বাস্তবায়িত হয়

১ · রিভিউ প্রসেস — Apple বনাম Google

L53-এর CI/CD পাইপলাইন একটি বৈধ, সাইনড .ipa/.apk তৈরি করে দেয় — কিন্তু সেই আর্টিফ্যাক্টটি সরাসরি ব্যবহারকারীর কাছে পৌঁছায় না। প্রতিটি প্ল্যাটফর্মের নিজস্ব স্টোর একটি রিভিউ ধাপ চালায়, এবং দুই প্ল্যাটফর্মের পদ্ধতি ভিন্ন — এগুলো ভালোভাবে-প্রতিষ্ঠিত, বহুল-নথিভুক্ত নীতি, তাই এখানে শুধু সাধারণভাবে-স্বীকৃত বৈশিষ্ট্যগুলো তুলে ধরা হচ্ছে।

Apple App Store
App Review টিমের একটি ম্যানুয়াল মানব-রিভিউ ধাপ আছে — অ্যাপ নীতিমালা-লঙ্ঘন বা মান-সংক্রান্ত কারণে প্রত্যাখ্যাত হতে পারে; সাধারণত এতে কিছুটা বেশি সময় লাগে।
Google Play
রিভিউ প্রক্রিয়া তুলনামূলকভাবে বেশি স্বয়ংক্রিয় (স্বয়ংক্রিয় স্ক্যান/নীতি-চেক), যদিও গুরুতর নীতিমালা-লঙ্ঘনের ক্ষেত্রে মানব-পর্যালোচনাও ঘটে; সাধারণত দ্রুততর।
ফেজড রিলিজ (App Store)
একটি নতুন ভার্সন সাত দিনে ধীরে ধীরে ১০০%-এ পৌঁছায় — কোনো সমস্যা দেখা দিলে ডেভেলপার থামাতে পারেন।
স্টেজড রোলআউট (Play)
ডেভেলপার নিজে একটি নির্দিষ্ট শতাংশ নির্বাচন করে রোলআউট শুরু করেন, প্রয়োজনে যেকোনো সময় হল্ট বা রোলব্যাক করতে পারেন।

২ · একটি সত্যিকারের স্টেজড-রোলআউট সিমুলেশন

নিচের কোড সেলে একটি ৪-ধাপের রোলআউট শিডিউল (১% → ১০% → ৫০% → ১০০%) একটি ২০ লাখ ব্যবহারকারীর বেস-এর উপর সিমুলেট করা হচ্ছে। প্রতিটি ধাপে বাস্তবে কতজন ব্যবহারকারী নতুন সংস্করণে থাকবেন তা round(total_users * percentage) দিয়ে হিসাব করা হয়, আর প্রতিটি ধাপের একটি সিমুলেটেড ক্র্যাশ-রেট একটি থ্রেশহোল্ডের বিরুদ্ধে যাচাই করা হয় — থ্রেশহোল্ড অতিক্রম করলে রোলআউট সত্যিই থেমে যায়, পরের ধাপগুলো একবারও চালানো হয় না।

Python
ROLLOUT_SCHEDULE = [
    ("দিন ১", 0.01),
    ("দিন ২", 0.10),
    ("দিন ৪", 0.50),
    ("দিন ৭", 1.00),
]

# প্রতিটি পর্যায়ে পরিমাপকৃত (সিমুলেটেড, deterministic) ক্র্যাশ রেট
CRASH_RATE_BY_STAGE = {
    0.01: 0.004,   # ১% পর্যায়ে -- স্বাভাবিক
    0.10: 0.031,   # ১০% পর্যায়ে -- থ্রেশহোল্ড অতিক্রম করে
    0.50: 0.006,   # (এই পর্যায়ে পৌঁছানো উচিত নয়)
    1.00: 0.005,   # (এই পর্যায়ে পৌঁছানো উচিত নয়)
}
CRASH_RATE_THRESHOLD = 0.02   # ২% -- এর বেশি হলে রোলআউট বন্ধ

def run_staged_rollout(total_users, schedule, crash_rates, threshold):
    """schedule অনুযায়ী ধাপে ধাপে রোলআউট চালায়। কোনো ধাপে crash_rate থ্রেশহোল্ড
    অতিক্রম করলে সেখানেই থেমে যায় -- পরের ধাপগুলো সত্যিই আর চালানো হয় না।
    রিটার্ন করে: (halted_at, current_live_users)।"""
    halted = False
    halted_at = None
    current_live_users = 0
    for day_label, pct in schedule:
        if halted:
            print(f"  {day_label:6s} | {pct*100:5.1f}% -- SKIPPED (আগেই রোলআউট বন্ধ করা হয়েছে)")
            continue
        active_users = round(total_users * pct)
        current_live_users = active_users
        crash_rate = crash_rates[pct]
        if crash_rate > threshold:
            status = "থ্রেশহোল্ড অতিক্রম -- রোলআউট বন্ধ"
            halted = True
            halted_at = day_label
        else:
            status = "স্বাভাবিক -- চালিয়ে যাওয়া হচ্ছে"
        print(f"  {day_label:6s} | {pct*100:5.1f}% -> {active_users:,} ইউজার | ক্র্যাশ রেট {crash_rate*100:.1f}% | {status}")
    return halted_at, current_live_users

TOTAL_USERS = 2_000_000
print(f"== স্টেজড রোলআউট সিমুলেশন (মোট ইউজার: {TOTAL_USERS:,}) ==")
halted_at, live_users = run_staged_rollout(TOTAL_USERS, ROLLOUT_SCHEDULE, CRASH_RATE_BY_STAGE, CRASH_RATE_THRESHOLD)

if halted_at:
    print(f"\nসিদ্ধান্ত: '{halted_at}' পর্যায়ে ক্র্যাশ রেট থ্রেশহোল্ডের বেশি হওয়ায় রোলআউট বন্ধ করা হয়েছে -- "
          f"বাকি {TOTAL_USERS - live_users:,} জন ব্যবহারকারী এখনো আগের স্থিতিশীল সংস্করণেই আছেন।")
else:
    print("\nসিদ্ধান্ত: সম্পূর্ণ রোলআউট সফলভাবে ১০০%-এ পৌঁছেছে।")

assert halted_at == "দিন ২", f"প্রত্যাশিত 'দিন ২'-তে থামার কথা, পাওয়া গেছে: {halted_at}"
assert live_users == 200_000, f"প্রত্যাশিত 200,000 ইউজার, পাওয়া গেছে: {live_users}"
print(f"\nযাচাই সফল: রোলআউট '{halted_at}'-এ থেমেছে, বর্তমানে {live_users:,} জন ({live_users/TOTAL_USERS*100:.0f}%) "
      f"নতুন সংস্করণে আছেন -- '৫০%' ও '১০০%' ধাপ কখনো চালানোই হয়নি।")

    
"দিন ১"-এ active_users = round(2,000,000 * 0.01) = 20,000 আর ক্র্যাশ রেট ০.৪% — থ্রেশহোল্ড (২%)-এর নিচে, তাই রোলআউট চলতে থাকে। "দিন ২"-এ active_users = round(2,000,000 * 0.10) = 200,000 আর ক্র্যাশ রেট ৩.১% — crash_rate > threshold সত্যি হয়ে যাওয়ায় halted = True সেট হয়ে যায়। এরপর লুপ "দিন ৪" ও "দিন ৭"-এ পৌঁছালেও if halted শর্তটি সত্যি থাকায় সেগুলো শুধু "SKIPPED" প্রিন্ট করে — active_users বা crash_rate সংক্রান্ত কোনো হিসাবই আর হয় না, এবং current_live_users-এর মান "দিন ২"-এর ২,০০,০০০-এই আটকে থাকে। এটাই রোলব্যাক সিদ্ধান্তের বাস্তব রূপ — একটি প্রকৃত if শর্ত মেট্রিককে থ্রেশহোল্ডের বিরুদ্ধে যাচাই করে সত্যিকারের নিয়ন্ত্রণ নেয়, শুধু বর্ণনামূলক প্রিন্ট নয়।
মূল কথা · Key takeaway

App Store ও Play Store-এর রিভিউ প্রক্রিয়া ভিন্ন হলেও (ম্যানুয়াল বনাম বেশি স্বয়ংক্রিয়), উভয় প্ল্যাটফর্মই রিলিজ-পরবর্তী ঝুঁকি কমাতে স্টেজড রোলআউট সমর্থন করে — একবারে ১০০% ব্যবহারকারীকে নতুন সংস্করণে না নিয়ে ধাপে ধাপে এক্সপোজার বাড়ানো হয়, যাতে একটি ক্র্যাশ-রেট স্পাইকের মতো সমস্যা মাত্র কয়েক হাজার ব্যবহারকারীর মধ্যে সীমাবদ্ধ থাকে, পুরো ব্যবহারকারী-বেসে ছড়িয়ে না পড়ে। উপরের সিমুলেশন দেখিয়েছে এই সিদ্ধান্তটি কোনো বিমূর্ত নীতি নয় — একটি মেট্রিক ও একটি থ্রেশহোল্ডের মধ্যে সরাসরি তুলনা করেই নেওয়া হয়।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ যদি রোলআউট একবারে ১০০%-এ শুরু হতো (স্টেজিং ছাড়া), তাহলে "দিন ২"-এর মতো একটি ক্র্যাশ-রেট স্পাইকের প্রভাব কত ব্যবহারকারীর উপর পড়ত?

পুরো ২০ লাখ ব্যবহারকারীর উপর — কারণ স্টেজিং ছাড়া প্রথম রিলিজেই সবাই নতুন সংস্করণে চলে যেতেন। উপরের সিমুলেশনে স্টেজিংয়ের কারণে সমস্যাটি মাত্র ২,০০,০০০ (মোট ব্যবহারকারীর ১০%) জনের মধ্যে সীমাবদ্ধ থাকে, কারণ "৫০%" ও "১০০%" ধাপ কখনো চালানোই হয়নি — এটাই স্টেজড রোলআউটের মূল সুরক্ষা-মূল্য।

প্র ০২ উপরের কোডে CRASH_RATE_BY_STAGE-এ "৫০%" ও "১০০%" পর্যায়ের ক্র্যাশ রেট আগে থেকেই সংজ্ঞায়িত করা আছে (যথাক্রমে ০.৬% ও ০.৫%), যদিও ওই পর্যায়ে রোলআউট কখনো পৌঁছায়নি — এটি কি একটি সমস্যা?

না — এই সংখ্যাগুলো ডিকশনারিতে সংজ্ঞায়িত থাকলেও কোডে সেগুলো কখনো পড়া (read) হয় না, কারণ if halted: শাখাটি crash_rates[pct] লাইনে কখনো পৌঁছায় না। বাস্তব জীবনের সাথে এটি মিলে যায় — "৫০%"/"১০০%" পর্যায়ে ব্যবহারকারীদের প্রকৃত অভিজ্ঞতা কখনোই ঘটেনি, তাই সেই সংখ্যাগুলো শুধু একটি কাল্পনিক/অব্যবহৃত ডেটা পয়েন্ট — কোডের আচরণ পরিবর্তন করে না।

প্র ০৩ App Store-এর ম্যানুয়াল মানব-রিভিউ ও Play Store-এর স্বয়ংক্রিয় রিভিউ — কোনটি ডেভেলপারের জন্য বেশি অনিশ্চয়তা তৈরি করতে পারে বলে মনে হয়, এবং কেন?

সাধারণত ম্যানুয়াল মানব-রিভিউ কিছুটা বেশি অনিশ্চয়তা তৈরি করে, কারণ একজন রিভিউয়ারের সিদ্ধান্ত ব্যক্তি-ভেদে কিছুটা ভিন্ন হতে পারে এবং প্রত্যাখ্যানের সুনির্দিষ্ট কারণ সবসময় তাৎক্ষণিকভাবে স্পষ্ট নাও হতে পারে — পুনরায় জমা দেওয়া ও অপেক্ষার একটি চক্র তৈরি হয়। স্বয়ংক্রিয় রিভিউ তুলনামূলকভাবে বেশি অনুমানযোগ্য ও দ্রুত, যদিও এটি সব ধরনের নীতিমালা-লঙ্ঘন সমানভাবে ধরতে পারে না বলে মাঝে মাঝে পরবর্তীতে ম্যানুয়াল হস্তক্ষেপও ঘটে।

অনুশীলন

  1. চিন্তা করুন: কেন একটি টিম প্রায়ই CRASH_RATE_THRESHOLD-এর মতো একটি সংখ্যা আগে থেকেই স্থির করে রাখে, রোলআউট চলাকালীন হাতে-হাতে সিদ্ধান্ত নেওয়ার বদলে?

    আগে থেকে থ্রেশহোল্ড ঠিক করে রাখলে সিদ্ধান্তটি বস্তুনিষ্ঠ ও দ্রুত হয় — একটি স্বয়ংক্রিয় সিস্টেম (বা অন-কল ইঞ্জিনিয়ার) কোনো বিতর্ক ছাড়াই তাৎক্ষণিকভাবে রোলব্যাক করতে পারে। রোলআউট চলাকালীন হাতে-হাতে সিদ্ধান্ত নিলে মূল্যবান সময় নষ্ট হয় (মিটিং, আলোচনা), এবং ততক্ষণে সমস্যাগ্রস্ত সংস্করণ আরও বেশি ব্যবহারকারীর কাছে পৌঁছে যেতে পারে — উপরের কোডে threshold প্যারামিটারটি ঠিক এই ভূমিকা পালন করে।

  2. পরীক্ষা করুন: উপরের কোড সেলে CRASH_RATE_BY_STAGE[0.10]-এর মান 0.031 থেকে 0.015-এ পরিবর্তন করুন (ধরে নিন "১০%" পর্যায়ে ক্র্যাশ রেট আসলে থ্রেশহোল্ডের নিচেই ছিল) এবং কোডটি আবার চালিয়ে দেখুন halted_at-এর মান কী হয়।

    0.015 > 0.02 মিথ্যা হওয়ায় "দিন ২"-এ আর রোলআউট থামবে না — লুপ "দিন ৪" ও "দিন ৭"-এও এগিয়ে যাবে (তাদের ক্র্যাশ রেটও থ্রেশহোল্ডের নিচে, ০.৬% ও ০.৫%), এবং শেষে halted_at None থাকবে — "সম্পূর্ণ রোলআউট সফলভাবে ১০০%-এ পৌঁছেছে" বার্তা প্রিন্ট হবে। এই পরিবর্তনের পর মূল assert halted_at == "দিন ২" লাইনটিও ব্যর্থ হবে, কারণ প্রত্যাশিত ফলাফল বদলে গেছে — এটি আবার মনে করিয়ে দেয় assert-গুলো সবসময় বর্তমান ডেটার সাথে সিঙ্কে রাখতে হয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ অ্যাপ লাইফসাইকেল, মোবাইল UI/UX, MVVM/MVI আর্কিটেকচার, নেটিভ বনাম ক্রস-প্ল্যাটফর্ম, নেভিগেশন, স্টেট ম্যানেজমেন্ট, লোকাল স্টোরেজ, ডিভাইস ফিচার ও ডিপ্লয়মেন্ট — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
  • L53 · মোবাইল অ্যাপের জন্য CI/CD আগের পাঠ যে পাইপলাইন এই পাঠের রিলিজ-যোগ্য বিল্ড তৈরি করে দেয়, তা সেই পাঠেই দেখানো হয়েছে।
  • সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics, Full-Stack Web Frameworks ও Mobile App Development — সব এক জায়গায়।
আগের পাঠ
মোবাইল অ্যাপের জন্য CI/CD