Node.js 26.5.0 এখন উপলব্ধ। এটি একটি Current রিলিজ, কোনো LTS ব্রাঞ্চ নয়, তাই এটি প্ল্যাটফর্মের সক্ষমতার একদম অগ্রভাগে অবস্থান করছে। এই পার্থক্যটি গুরুত্বপূর্ণ। আঠারো মাসের স্থিতিশীলতা প্রত্যাশা করে এমন কোনো প্রোডাকশন ফ্লিটে (production fleet) এটি অন্ধভাবে পরিবর্তন করা উচিত নয়। কিন্তু এই ছোট এবং দ্রুত রিলিজগুলোর মাধ্যমেই আপনি ভবিষ্যতের রূপরেখা দেখতে পাবেন। এগুলো দেখায় যে মেইনটেইনাররা কোন API গুলোকে আরও উন্নত করছেন এবং রানটাইম পরবর্তী কোন দিকে যাচ্ছে। 26.5.0 সংস্করণে, প্রধান কাজগুলো Web Streams API-তে করা হয়েছে, যেখানে কিছু নির্দিষ্ট ফিক্স (fixes) Node-কে ব্রাউজারের সমপর্যায়ে নিয়ে আসার জন্য আরও এক ধাপ এগিয়ে দিয়েছে। এই রিলিজটি ফাইল সিস্টেম এবং URL হ্যান্ডলিং লেয়ারের দুটি ত্রুটিও সংশোধন করেছে।
Node.js-এ Web Streams কী করছে?
আপনি যদি দীর্ঘ সময় ধরে Node-এ স্ট্রিমিং কোড লিখে থাকেন, তবে আপনি জানেন যে বিল্ট-ইন stream মডিউলটির নিজস্ব বৈশিষ্ট্য রয়েছে। Readable, Writable, Transform, এবং Duplex বছরের পর বছর ধরে এই ইকোসিস্টেমের মূল চালিকাশক্তি হিসেবে কাজ করছে। এগুলো শক্তিশালী, কিন্তু ব্রাউজারে আপনি যে স্ট্রিমগুলোর দেখা পান তার সাথে এগুলো এক নয়। যখন আপনি একটি ফ্রন্ট-এন্ড সার্ভিস ওয়ার্কার (service worker) এবং একটি ব্যাক-এন্ড রুট হ্যান্ডলারের মধ্যে লজিক শেয়ার করার চেষ্টা করেন, তখন এই ব্যবধানটি সমস্যার সৃষ্টি করে। এর ফলে আপনাকে অ্যাডাপ্টার পুনরায় লিখতে হয়, ডেটাকে অপরিচিত ফরম্যাটে কপি করতে হয়, অথবা শেয়ারড কোড পুরোপুরি এড়িয়ে চলতে হয়।
Web Streams API তৈরি করা হয়েছে সেই ব্যবধানটি দূর করার জন্য। এটি সেই একই স্ট্যান্ডার্ড যা ব্রাউজারে fetch বডি হ্যান্ডলিং পরিচালনা করে। এটিকে Node-এ নিয়ে আসার মাধ্যমে, প্রজেক্টটি আপনাকে একবার স্ট্রিমিং লজিক লিখে যেকোনো পরিবেশে চালানোর সুযোগ দেয়। এই API-টি ReadableStream, WritableStream, এবং TransformStream অবজেক্ট নিয়ে কাজ করে যা একটি ইউনিফর্ম ইন্টারফেসের মাধ্যমে চাঙ্ক (chunks) পাস করে। সংস্করণ 26.5.0 সেই ইন্টারফেসটি পুনরায় লিখছে না, তবে এটি দুটি গুরুত্বপূর্ণ বিষয় আরও সুসংহত করেছে।
releaseLock ফিক্স করা এবং BYOB Reader-এর ত্রুটি সংশোধন
এই রিলিজের একটি সুনির্দিষ্ট পরিবর্তন হলো WritableStreamDefaultWriter-এর releaseLock মেথডটির একটি ফিক্স। Web Streams মডেলে, একটি রাইটার লক (writer lock) একাধিক কনজিউমারকে একই সাথে একই স্ট্রিমের ওপর কাজ করা থেকে বিরত রাখে। যখন আপনি releaseLock() কল করেন, তখন আপনি সংকেত দিচ্ছেন যে আপনার রাইটার কাজ শেষ করেছে এবং নিচের স্ট্রিমটি পরবর্তী অপারেশনের জন্য মুক্ত। এখানে একটি ত্রুটিপূর্ণ ইমপ্লিমেন্টেশন স্ট্রিমটিকে অনিশ্চিত অবস্থায় (limbo) ফেলে রাখতে পারে, যেখানে রাইটার চলে যাওয়ার পরেও স্ট্রিমটি মনে করে যে এটি এখনও দখলকৃত। আপলোড পার্স করা বা স্টোরেজে ডেটা পাইপ করার মতো ব্যস্ত সার্ভারের ক্ষেত্রে, এই ধরনের একটি পুরনো লক (stale lock) পাইপলাইনকে আটকে দিতে পারে বা এমন ত্রুটি তৈরি করতে পারে যা উৎস খুঁজে বের করা কঠিন। 26.5.0-এর ফিক্সটি এই হ্যান্ডঅফ (handoff) প্রক্রিয়াকে আবারও অনুমানযোগ্য করে তুলেছে।
দ্বিতীয় Web Streams পরিবর্তনটি ReadableStream এবং TransformStream-এর সাথে BYOB রিডার কীভাবে কাজ করে তা উন্নত করে। BYOB মানে হলো Bring Your Own Buffer। স্ট্রিমটি প্রতিবার ডেটা দেওয়ার সময় নতুন মেমরি চাঙ্ক বরাদ্দ করার পরিবর্তে, আপনি এটিকে একটি বাফার প্রদান করেন যা আপনি আগে থেকেই আলাদা করে রেখেছেন। স্ট্রিমটি সেই বাফারটি পূর্ণ করে, আপনি বাইটগুলো প্রসেস করেন এবং তারপর পুনরায় ব্যবহারের জন্য সেই একই বাফারটি ফেরত দেন। এটি একটি ছোট যান্ত্রিক পার্থক্য যা বিশাল পরিমাণ ডেটা মুভ করার সময় অসাধারণ ফলাফল দেয়।
Node-এ কিছু সময় ধরে BYOB সাপোর্ট থাকলেও, ReadableStream এবং TransformStream-এর কিছু এজ কেস (edge cases) BYOB রিডার যুক্ত করার সময় ভুল আচরণ করতে পারত। ফিক্সটির সুনির্দিষ্ট বিবরণ অপেক্ষা এর ব্যবহারিক ফলাফলটি বেশি গুরুত্বপূর্ণ: এখন থেকে এক্সপ্লিসিট বাফার (explicit buffers) ব্যবহারকারী স্ট্রিমগুলো রিডিং এবং ট্রান্সফরমেশন—উভয় পর্যায়েই আরও নির্ভরযোগ্য। ব্যাকপ্রেশার (backpressure) ইভেন্টের সময় অদ্ভুত ত্রুটির কারণে আপনি যদি BYOB রিডার এড়িয়ে চলেন, তবে এই রিলিজটি তা এড়িয়ে চলার একটি কারণ কমিয়ে দিয়েছে।
BYOB আসলে কোথায় কাজে লাগে
তাত্ত্বিকভাবে বা অ্যাবস্ট্রাক্টভাবে বাফার পুনরায় ব্যবহার নিয়ে কথা বলা সহজ। কিন্তু এটি কোথায় গুরুত্বপূর্ণ তা নিয়ে ভাবা বেশি কার্যকর।
কল্পনা করুন আপনি এমন একটি সার্ভিস লিখছেন যা টেলিমেট্রি আপলোড গ্রহণ করে। সেই আপলোডগুলো হতে পারে কম্প্রেসড লগ বা র (raw) সেন্সর ডাম্প, যার প্রতিটির সাইজ কয়েকশ মেগাবাইট। যদি স্ট্রিমটি ডেটার প্রতিটি স্লাইসের জন্য একটি নতুন Node Buffer বরাদ্দ করে, তবে গার্বেজ কালেক্টরকে অতিরিক্ত কাজ করতে হয় এবং মেমরি স্পাইক দ্রুত বাড়তে থাকে। একটি BYOB রিডারের মাধ্যমে, আপনি স্টার্টআপের সময় একটি সীমিত সংখ্যক বাফারের পুল বরাদ্দ করেন। স্ট্রিমটি সেগুলো পূর্ণ করে, আপনার পার্সার সেগুলো ব্যবহার করে শেষ করে এবং সেগুলো পুনরায় ব্যবহারের জন্য ফিরে আসে। ফলে মেমরি স্থিতিশীল থাকে। একই নিয়ম তখনো প্রযোজ্য হয় যখন আপনি দুটি সকেটের মধ্যে নেটওয়ার্ক ট্রাফিক প্রক্সি করছেন অথবা পুরো ফাইলটি RAM-এ লোড না করে লাইন বাই লাইন বড় CSV ফাইল পার্স করছেন।
এখানে ট্রান্সফর্ম স্ট্রিমগুলোও সমানভাবে গুরুত্বপূর্ণ। একটি TransformStream পাইপলাইনের মাঝখানে থাকে, যা হয়তো একটি gzip স্ট্রিমকে ডিকম্প্রেস করে অথবা রিয়েল-টাইমে চাঙ্কগুলোকে (chunks) এনক্রিপ্ট করে। যদি ট্রান্সফর্ম ধাপটি BYOB বাফারগুলোকে সঠিকভাবে পরিচালনা করতে না পারে, তবে আপনি করাপ্টেড আউটপুট, ড্রপ হওয়া চাঙ্ক বা লোডের সময় স্টল (stalls) দেখতে পারেন। 26.5.0 ভার্সনের ফিক্সগুলো ঠিক এই ধরনের পাইপলাইন সমস্যাগুলো সমাধান করে, আর এই কারণেই যারা হাই-থ্রুপুট I/O ব্যবহার করছেন তাদের এটি খেয়াল করা উচিত।
নিঃশব্দ বিজয়: ফাইল সিস্টেম এবং এরর ক্লিয়ারিটি (Error Clarity)
26.5.0-এ সবকিছু শুধু স্ট্রিমিং নিয়ে নয়। এই রিলিজটি fs.rm এবং fs.rmSync-এর আচরণও ঠিক করেছে যখন recursive অপশনটি false সেট করা থাকে। আগে, একটি ডিরেক্টরি পাথের সাথে recursive: false পাস করলে ক্লিনআপের সময় অপ্রত্যাশিত ফলাফল আসতে পারত। মেথডটি এমনভাবে কাজ করতে পারত যা কলারের (caller) স্পষ্ট উদ্দেশ্যের সাথে মিলত না; যেমন প্রত্যাশার চেয়ে বেশি কিছু ডিলিট করে ফেলা অথবা প্ল্যাটফর্মের ওপর ভিত্তি করে অসংলগ্নভাবে ব্যর্থ হওয়া। ফাইল ক্লিনআপ এমন একটি অপারেশন যা বোরিং এবং প্রেডিক্টেবল (পূর্বাভাসযোগ্য) হওয়া উচিত। বোরিং হওয়া মানেই ভালো। এই ফিক্সটি সেই প্রেডিক্টেবিলিটি ফিরিয়ে আনে, যাতে আপনার টেম্পোরারি ডিরেক্টরি ক্লিনআপ স্ক্রিপ্ট বা ডিপ্লয়মেন্ট টিয়ারডাউন লজিক ঠিক কোড অনুযায়ী কাজ করে।
URL.canParse কীভাবে ফেইলর রিপোর্ট করে, তার ক্ষেত্রেও একটি কোয়ালিটি-অফ-লাইফ ইমপ্রুভমেন্ট আনা হয়েছে। মেথডটি কোনো ইনপুট ভুল (malformed) হলেও এরর থ্রো না করে একটি স্ট্রিং বৈধ URL কি না তা পরীক্ষা করে। 26.5.0-এ, কোনো সমস্যা হলে এটি এখন আরও উন্নত Error.cause তথ্য প্রদান করে। মূল কারণটি লুকিয়ে না রেখে, এরর অবজেক্টটি একটি কজাল চেইন (causal chain) সংরক্ষণ করে। এর মানে হলো, যখন কোনো ভ্যালিডেশন হেল্পারের ভেতরে URL পার্সিং ব্যর্থ হয়, তখন আপনার লগ করা স্ট্যাক আপনাকে বলে দেবে যে সমস্যাটি কি একটি ভুল প্রোটোকল, মিসিং হোস্টনেম নাকি অন্য কোনো স্ট্রাকচারাল সমস্যা ছিল। ফলে আপনাকে প্রতিটি কল সাইটে ম্যানুয়াল ডিবাগ লগ ছড়িয়ে দিতে হবে না।
আপনার কি আপগ্রেড করা উচিত?
উত্তরটি নির্ভর করছে আপনি কী ব্যবহার করছেন তার ওপর।
যদি আপনার প্রোডাকশন ওয়ার্কলোড v20.x লাইনের মতো কোনো LTS ভার্সনে থাকে, তবে সেখানেই থাকুন। এই ফিক্সগুলো শেষ পর্যন্ত ব্যাকপোর্ট করা হবে অথবা পরবর্তী অ্যাক্টিভ LTS-এ আসবে। একটি সার্ভার যা ইতিমধ্যে ঠিকঠাক কাজ করছে, সেখানে সামান্য স্মুদার স্ট্রিম লক বা আরও পরিষ্কার URL এরর পাওয়ার সুবিধার চেয়ে স্ট্যাবিলিটি এবং প্রেডিক্টেবল সাপোর্ট টাইমলাইন বেশি গুরুত্বপূর্ণ।
আপনি যদি নতুন কোনো সার্ভিস তৈরি করেন, রিয়েল-টাইম ডেটা পাইপলাইনের প্রোটোটাইপ বানান, অথবা পারফরম্যান্স-ক্রিটিক্যাল I/O-এর জন্য Web Streams API সক্রিয়ভাবে ব্যবহার করেন, তবে 26.5.0-এ আপগ্রেড করা সার্থক হবে। Node streams এবং ব্রাউজার Web Streams-এর মধ্যে এই ক্রমবর্ধমান সামঞ্জস্যতা কেবল একটি কম্প্যাটিবিলিটি জয় নয়। এটি একটি আরও ইউনিফাইড JavaScript রানটাইমের ওপর বাজি ধরা, যেখানে কোনো ট্রান্সলেশন লেয়ার ছাড়াই একই ডেটা-পুশিং লজিক সার্ভার এবং ক্লায়েন্টের মধ্যে আদান-প্রদান করা যাবে। এটি কগনিটিভ লোড কমায় এবং আপনার টিম যখন উভয় এনভায়রনমেন্টের জন্য কোড শিপ করে, তখন বাগের সম্ভাবনাও কমিয়ে দেয়।
এই রিলিজটি ছোট, কিন্তু এর দিকনির্দেশনা স্পষ্ট। Node এমন সব স্ট্যান্ডার্ড-ভিত্তিক API-তে বিনিয়োগ অব্যাহত রেখেছে যা যেখানেই JavaScript চলে সেখানেই কাজ করে। Web Streams-এর উন্নতিগুলো হয়তো বড় কোনো হেডলাইন ফিচার নয়, কিন্তু এগুলো এমন একটি পথকে মসৃণ করে যা বছরের পর বছর ধরে অস্থিতিশীল ছিল। আপনি যদি Current লাইনে থাকেন তবে 26.5.0 নিয়ে নিন, আর সময়মতো এই ফিক্সগুলো আপনার LTS ওয়ার্ল্ডে আসার জন্য অপেক্ষা করুন।
Source: Dev.to – Node.js 26.5.0: Web Streams এবং Error Handling-এ নতুন কী কী আছে
আলোচনায় যোগ দিন এবং Telegram-এ GyaanSetu কমিউনিটির সাথে শেখা চালিয়ে যান।
