সাধারণত, গ্লোবাল ভেরিয়েবল খারাপ। কিন্তু কখনও কখনও, সঠিক জায়গায় একটি গ্লোবাল আপনার কোডকে অনেক সহজ করে দিতে পারে৷
৷রেলে, আপনি অনুরোধের সময় একবার ডেটা সেট করতে পারেন, তবে আপনার অ্যাপের প্রতিটি স্তরে এটি ব্যবহার করুন। কোন ব্যবহারকারী অনুরোধ করছেন? তাদের কি অনুমতি আছে? কোন ডাটাবেস সংযোগ ব্যবহার করা উচিত?
এই তথ্যটি আপনার কোড জুড়ে উপলব্ধ হওয়া উচিত, তাই এটিকে সর্বত্র পাস করা কেবলমাত্র গোলমাল হবে। কিন্তু একটি রুবি গ্লোবাল ভেরিয়েবল ব্যবহার করা, বা একটি ক্লাস ভেরিয়েবল সেট করা তার নিজস্ব সমস্যা তৈরি করবে। একাধিক থ্রেড এটিকে ওভাররাইট করতে পারে, এবং আপনি একটি বিশাল জগাখিচুড়ির সাথে শেষ হবেন, এবং হয়ত অনাকাঙ্ক্ষিতভাবে খারাপ ডেটা।
আপনার এমন কিছু দরকার যা বিশ্বব্যাপী, কিন্তু শুধুমাত্র আপনার অনুরোধের জন্য .
সমতল রুবি পথ
সাধারণত, আপনি এটি Thread.current[]
দিয়ে পরিচালনা করা দেখতে পাবেন . এটা এই মত দেখায়:
Thread.current[:current_user] = user
এই যথেষ্ট সহজ. এটি একটি শালীন সমাধান। কিন্তু এর দুটি বড় অপূর্ণতা রয়েছে:
-
কেউ ভুলবশত আপনার ডেটা ওভাররাইট করতে পারে৷৷
যদি দুইজন একই চাবি বাছাই করে? আপনি একে অপরের ডেটা স্টম্প করবেন। এবং আপনি যদি ব্যবহারকারীদের মতো কিছু সঞ্চয় করেন তবে এটি গুরুতরভাবে খারাপ হবে। আপনার নিজের অ্যাপে, এটি সম্ভবত একটি সমস্যা হবে না। কিন্তু আপনি যদি রত্ন লিখছেন, বা আপনার Rails অ্যাপটি বড় এবং অগোছালো হয়, তাহলে এটি এমন কিছু যা আপনাকে ভাবতে হবে।
-
এটি সুগঠিত নয়৷৷
Thread.current[]
তথ্যের একটি বড় ব্যাগ মাত্র। আপনি সহজেই এটি নথিভুক্ত করতে পারবেন না। আপনি যদি এটি থেকে কী বের করতে পারেন তা জানতে চান তবে আপনি এতে কী রেখেছেন তা অনুসন্ধান করতে হবে৷অবশ্যই, আপনি যদি পর্যাপ্ত গ্লোবাল ডেটা ফেলে দিচ্ছেন যে এটি একটি সমস্যা, তাহলে আপনাকে
Thread.current[]
এর চেয়ে বেশি চিন্তা করতে হবে। এর কাঠামোর অভাব। তবে এটি এখনও মনে রাখা একটি বিন্দু।
সুতরাং, Thread.current[]
এর চেয়ে ভাল সমাধান আছে কি ? আপনি কল্পনা করতে পারেন, রেল নিজেই অনেক অনুরোধ-স্থানীয় ডেটা পরিচালনা করে। এবং গুডির বাক্স যা ActiveSupport এর অনুসরণ করার জন্য একটি ভিন্ন প্যাটার্ন রয়েছে।
রেল পথ
আপনি যদি ActiveSupport-এর মাধ্যমে খনন করেন, তাহলে আপনি ActiveSupport::PerThreadRegistry
এ যেতে পারেন . আপনি সম্ভবত নাম থেকে বলতে পারেন যে আমরা যা খুঁজছি ঠিক এটিই।
ActiveSupport::PerThreadRegistry
সহ , আগের উদাহরণটি এইরকম দেখাবে:
class RequestRegistry
extend ActiveSupport::PerThreadRegistry
attr_accessor :current_user, :current_permissions
end
RequestRegistry.current_user = user
RequestRegistry.current_user # => user
এটি একটি ছোট বিট আরো কাজ. কিন্তু ActiveSupport::PerThreadRegistry
এর সাথে :
-
আপনার কাছে ডকুমেন্টেশন রাখার জায়গা আছে। আপনার ক্লাসের দিকে তাকিয়ে থাকা যে কেউ জানতে পারবে আপনি ঠিক কোন গ্লোবাল ডেটা আশা করছেন এবং তারা কোন গ্লোবাল ডেটা ব্যবহার করতে পারে।
-
আপনি একটি API পাবেন যা দেখতে ভালো। আসলে, দেখে মনে হচ্ছে আপনি শুধু ক্লাস ভেরিয়েবল সেট করছেন। থ্রেড নিয়ে চিন্তা করতে না হলে সম্ভবত আপনি এটাই করতেন।
-
ক্লাসে আপনার সেট করা যেকোনো ডেটা নামস্থানে থাকবে। আপনাকে
RequestRegistry.current_user
নিয়ে চিন্তা করতে হবে নাPhoneNumberApiRegistry.current_user
এর সাথে সংঘর্ষ , তাদের সম্পূর্ণ আলাদাভাবে চিকিৎসা করা হয়।
রেল ActiveSupport::PerThreadRegistry
ব্যবহার করে অভ্যন্তরীণভাবে, ActiveRecord কানেকশন হ্যান্ডলিং, এক্সপ্লেন ক্যোয়ারী স্টোর করা এবং ActiveSupport::Notifications এর মতো জিনিসের জন্য। সুতরাং আপনি যদি PerThreadRegistry
এর ক্ষমতার আরও ভাল উদাহরণ খুঁজছেন , রেল নিজেই শুরু করার জন্য একটি দুর্দান্ত জায়গা।
যখন থ্রেড এবং অনুরোধ মেলে না
কিছু রেল সার্ভারের জন্য, একটি একক থ্রেড একাধিক অনুরোধ পরিচালনা করে। এর মানে আপনি PerThreadRegistry
-এ যা কিছু রাখেন পরবর্তী অনুরোধের জন্য কাছাকাছি থাকবে. এটি সম্ভবত আপনি যা চান তা নয়৷
রেল যা করে তা আপনি করতে পারেন এবং PerThreadRegistry
-এ আপনি যে জিনিসগুলি রাখেন তা পরিষ্কার করতে পারেন আপনি তাদের সাথে সম্পন্ন করার পরে। আপনি সেখানে কি রেখেছেন তার উপর নির্ভর করে, আপনি যেভাবেই হোক এটি করছেন।
মন্তব্যে, MattB একটি সহজ সমাধান নির্দেশ করে:request_store। এটি Thread.current[]
এর মত কাজ করে , কিন্তু প্রতিটি অনুরোধের পরে নিজেকে পরিষ্কার করে।
এটি কারোর জন্য PerRequestRegistry
তৈরি করার জন্য দরজা খোলা রাখে , যা PerThreadRegistry
-এর API-এর সাথে request_store-এর নিরাপত্তাকে একত্রিত করে . যদি কেউ এটি ইতিমধ্যেই করে থাকে, আমি এটি সম্পর্কে শুনতে চাই!
এটি ব্যবহার করে দেখুন
৷গ্লোবাল ডেটা খারাপ হতে পারে। অত্যধিক গ্লোবাল দ্রুত অরক্ষণীয় কোডের দিকে নিয়ে যেতে পারে৷
কিন্তু পুরো অনুরোধের জন্য যদি ডেটা কেন্দ্রীয় জায়গায় রাখাটা বোধগম্য হয়, তাহলে Thread.current[]
. ActiveSupport::PerThreadRegistry
দিন অথবা একটি শট অনুরোধ করুন. অন্য কিছু না হলে, এটি গ্লোবাল ডেটা নিয়ে কাজ করাকে একটু কম ঝুঁকিপূর্ণ করে তুলবে।