एक टोकन बाल्टी लागू करने के लिए काफी सरल है।
5 टोकनों के साथ एक बाल्टी के साथ शुरू करें।
हर 5/8 सेकंड: अगर बाल्टी में 5 से कम टोकन हैं, तो एक जोड़ें।
हर बार जब आप एक संदेश भेजना चाहते हैं: यदि बाल्टी में send1 टोकन हैं, तो एक टोकन बाहर ले जाएं और संदेश भेजें। अन्यथा, प्रतीक्षा करें / संदेश छोड़ दें / जो भी हो।
(स्पष्ट रूप से, वास्तविक कोड में, आप वास्तविक टोकन के बजाय पूर्णांक काउंटर का उपयोग करेंगे और आप टाइमस्टैम्प्स को संग्रहीत करके प्रत्येक 5 / 8s चरण का अनुकूलन कर सकते हैं)
प्रश्न को फिर से पढ़ना, अगर दर सीमा पूरी तरह से प्रत्येक 8 सेकंड में रीसेट हो जाती है, तो यहां एक संशोधन है:
टाइमस्टैम्प से शुरू करें last_send
, एक समय पहले (जैसे, युग में)। इसके अलावा, उसी 5-टोकन बाल्टी के साथ शुरू करें।
हर 5/8 सेकंड के नियम पर प्रहार करें।
हर बार जब आप एक संदेश भेजते हैं: पहले, जांचें कि message last_send
8 सेकंड पहले। यदि ऐसा है, तो बाल्टी भरें (इसे 5 टोकन पर सेट करें)। दूसरा, अगर बाल्टी में टोकन हैं, तो संदेश भेजें (अन्यथा, ड्रॉप / प्रतीक्षा / आदि।)। तीसरा, last_send
अब के लिए सेट ।
उस परिदृश्य के लिए काम करना चाहिए।
मैंने वास्तव में इस तरह की रणनीति (पहला दृष्टिकोण) का उपयोग करके आईआरसी बॉट लिखा है। पर्थ में इसका, पायथन नहीं है, लेकिन यहाँ वर्णन करने के लिए कुछ कोड है:
यहाँ पहला भाग बाल्टी में टोकन जोड़ने का काम करता है। आप समय (दूसरी से अंतिम पंक्ति) के आधार पर टोकन जोड़ने का अनुकूलन देख सकते हैं और फिर अंतिम पंक्ति अधिकतम करने के लिए बाल्टी सामग्री (MESSAGE_BURST)
my $start_time = time;
...
# Bucket handling
my $bucket = $conn->{fujiko_limit_bucket};
my $lasttx = $conn->{fujiko_limit_lasttx};
$bucket += ($start_time-$lasttx)/MESSAGE_INTERVAL;
($bucket <= MESSAGE_BURST) or $bucket = MESSAGE_BURST;
$ कॉन एक डेटा संरचना है जो चारों ओर से गुजरती है। यह एक विधि के अंदर है जो नियमित रूप से चलता है (यह गणना करता है कि अगली बार जब यह करने के लिए कुछ होगा, और तब तक या तो सोता है या जब तक यह नेटवर्क ट्रैफ़िक प्राप्त नहीं करता है)। विधि का अगला भाग भेजना संभालता है। यह बल्कि जटिल है, क्योंकि संदेशों में उनसे जुड़ी प्राथमिकताएँ होती हैं।
# Queue handling. Start with the ultimate queue.
my $queues = $conn->{fujiko_queues};
foreach my $entry (@{$queues->[PRIORITY_ULTIMATE]}) {
# Ultimate is special. We run ultimate no matter what. Even if
# it sends the bucket negative.
--$bucket;
$entry->{code}(@{$entry->{args}});
}
$queues->[PRIORITY_ULTIMATE] = [];
यह पहली कतार है, जिसे चलाया नहीं जाता है। भले ही यह हमारे कनेक्शन को बाढ़ के लिए मार दिया जाए। अत्यंत महत्वपूर्ण चीजों के लिए उपयोग किया जाता है, जैसे कि सर्वर के पिंग का जवाब। अगला, शेष कतारें:
# Continue to the other queues, in order of priority.
QRUN: for (my $pri = PRIORITY_HIGH; $pri >= PRIORITY_JUNK; --$pri) {
my $queue = $queues->[$pri];
while (scalar(@$queue)) {
if ($bucket < 1) {
# continue later.
$need_more_time = 1;
last QRUN;
} else {
--$bucket;
my $entry = shift @$queue;
$entry->{code}(@{$entry->{args}});
}
}
}
अंत में, बाल्टी की स्थिति वापस $ कॉन डेटा संरचना में सहेज ली जाती है (वास्तव में विधि में थोड़ा बाद में; यह पहली बार गणना करता है कि यह कितनी जल्दी काम करेगा)
# Save status.
$conn->{fujiko_limit_bucket} = $bucket;
$conn->{fujiko_limit_lasttx} = $start_time;
जैसा कि आप देख सकते हैं, वास्तविक बाल्टी हैंडलिंग कोड बहुत छोटा है - लगभग चार लाइनें। बाकी कोड प्राथमिकता कतार हैंडलिंग है। बॉट की प्राथमिकता कतारें हैं, जैसे कि, इसके साथ चैट करने वाला कोई व्यक्ति इसे अपने महत्वपूर्ण किक / प्रतिबंध कर्तव्यों को करने से नहीं रोक सकता है।