2009-08-17 18 views
7

मैंने अपने अधिकांश ऐप को ओटीपी व्यवहारों में पोर्ट किया, लेकिन मैं फंस गया हूं। मैं एक gen_server का उपयोग कर चुनिंदा प्राप्त करने के तरीके को समझ नहीं सकता। यदि कोई भी कॉलबैक फ़ंक्शन खंड किसी संदेश से मेल नहीं खाता है, तो संदेश को मेलबॉक्स में वापस डालने के बजाय, यह त्रुटियां समाप्त हो जाती है!gen_servers में आप चुनिंदा प्राप्त कैसे करते हैं?

अब, हर जगह मैं जाता हूं, लोगों को चुनिंदा अधिग्रहण प्राप्त होता है। जहां भी मैं जाता हूं, लोग ओटीपी की प्रशंसा करते हैं। क्या यह वास्तव में सच हो सकता है कि आप दोनों एक साथ नहीं हो सकते हैं? क्या यह एक प्रमुख, सुधार योग्य कमी की तरह प्रतीत नहीं होता है?

एरलांग प्रोग्रामर इसे कैसे संभालते हैं?

संपादित करें (जेड की टिप्पणी का जवाब):

एक उदाहरण है जहाँ मैं क्रमबद्ध क्रम में मुद्रित पूर्णांकों की एक सूची देखना चाहते हैं क्या है:

-module(sel_recv). 
-behaviour(gen_server). 

-export([start_link/0]). 

-export([init/1, handle_call/3, handle_cast/2, handle_info/2, 
    terminate/2, code_change/3]). 

-export([test/0]). 

start_link() -> 
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). 

test() -> 
    gen_server:cast(?MODULE, test). 

init([]) -> 
    {ok, 0}. 

handle_call(_Request, _From, State) -> 
    Reply = ok, 
    {reply, Reply, State}. 

handle_cast(test, _State) -> 
    lists:map(fun(N) -> 
         gen_server:cast(?MODULE, {result, N}) 
       end, [9,8,7,6,5,4,3,2,1]), 
    {noreply, [1,2,4,5,6,7,8,9]}; 
handle_cast({result, N}, [N|R]) -> 
    io:format("result: " ++ integer_to_list(N) ++ "~n"), 
    {noreply, R}. 

handle_info(_Info, State) -> 
    {noreply, State}. 

terminate(_Reason, _State) -> 
    ok. 

code_change(_OldVsn, State, _Extra) -> 
    {ok, State}. 
बेशक

, मेरा असली अनुप्रयोग में, टाइमर देरी होती है और संदेशों को संसाधित करने की आवश्यकता होती है जो अन्य संदेशों के साथ मिलती हैं। विशेष रूप से, मैं http अनुरोध भेजता हूं, कभी-कभी कई बार, कभी-कभी एक समय में उनके बीच अंतराल के साथ। किसी भी मामले में, मुझे उन्हें क्रम में इकट्ठा करने की आवश्यकता है।

+0

आप क्या हासिल करना चाहते हैं? – Zed

उत्तर

4

Gen_server शायद इसके लिए सबसे अच्छा विकल्प नहीं है।

handle_cast(test, _State) -> 
    ... 
    {noreply, {[1,2,4,5,6,7,8,9], []}}; 

handle_cast({result, N}, {Wait, Buff}) -> 
    {noreply, handle_results(Wait, [N|Buff])}. 

handle_results([], Buff) -> 
    {[], Buff}; 

handle_results([W|WTail] = Wait, Buff) -> 
    case lists:member(W, Buff) of 
     true -> 
      io:format("result: " ++ integer_to_list(W) ++ "~n"), 
      handle_results(WTail, Buff -- [W]); 
     false -> 
      {Wait, Buff} 
    end. 
+0

बस पूर्णता के लिए, आप अपने सभी अवांछित संदेशों को अपने आप भेज सकते हैं (इस प्रकार इसे अपने मेलबॉक्स के अंत में ले जा सकते हैं)। इसमें कई समस्याएं हैं (आपका gen_server आगे थ्रोटल संदेशों पर काम करेगा, यह कार्यान्वयन विनिर्देशों का उपयोग करता है), इसलिए आपको इसे कभी भी उपयोग नहीं करना चाहिए :) हैंडलकास्ट (संदेश, राज्य) -> स्वयं()! {'$ gen_cast', संदेश}, {noreply, राज्य}। – Zed

+0

हाँ, मैंने इसे पहले माना था। बहुत संक्षिप्त रूप से। ;) आपका पहला विचार एक अच्छा है। सामान्य मामला यह है कि मुझे उन्हें संसाधित करने से पहले 8 आइटम एकत्र करने की आवश्यकता है। नौकरी में आमतौर पर 200 बैचों होंगे। मैं यह गणना करने की कोशिश कर रहा हूं कि आपकी विधि यहां प्रत्येक परिणाम को एक संख्या के साथ टैग करने और 8 आइटम प्राप्त होने के बाद प्रत्येक बैच को सॉर्ट करने से अधिक कुशल है या नहीं। – mwt

3

हो सकता है कि तुम सच में gen_fsm उपयोग करना चाहते हैं: एक बात आप कर सकते हैं चयनात्मक खुद प्राप्त एक बफर सूची में सभी संदेशों को प्राप्त करते हैं, और लागू करने के लिए है। उस व्यवहार को आम तौर पर प्रोटोकॉल के लिए फ्रंट-सिरों का चयन किया जाता है, जहां प्रोटोकॉल के कुछ राज्य होते हैं और वर्तमान में किस स्थिति में निर्भर करता है, इसके आधार पर अलग-अलग अनुरोधों को संभालने की आवश्यकता होती है।

लेकिन gen_server पर वापस, हम इसकी सुविधाओं के लिए gen_server का उपयोग करते हैं। यह कोड-लोडिंग के लिए सिस्टम इवेंट्स की सदस्यता लेता है और आपको कोड_चेंज कॉलबैक देता है। यह दुर्घटनाओं पर sasl-reports का कारण बनता है। आपको एक अच्छी तरह से ज्ञात संरचना मिलती है जो कोड रखरखाव में मदद करता है। सबसे महत्वपूर्ण बात यह है कि यह सिंक्रोनस कॉल के लिए एक अच्छी तरह से डिज़ाइन किया गया प्रोटोकॉल लागू करता है।

यह कहना मुश्किल है कि इस उदाहरण में ओटीपी व्यवहार आपके लिए सही हैं या नहीं।


टिप्पणी को देखते हुए, ऐसा लगता है कि आपके लिए gen_server गलत है। जब मैं gen_server व्यवहार का उपयोग करता हूं तो मैं इसे किसी कंपनी के मालिक के रूप में सोचता हूं। हर कोई मालिक के साथ बात करना चाहता है, इसलिए यह कंपनी के सबसे अच्छे हित में है कि मालिक को नौकरियों को जल्दी और कुशलतापूर्वक प्रतिनिधि बनाने में सक्षम बनाया जाए ताकि वह लोगों को काम करने की बजाय प्रतीक्षा करने न दे।

gen_server 'से' पैरामीटर का उपयोग करके प्रतिनिधि हो सकता है। ऐसा करने के लिए, {no_reply, State} वापस करें और प्रेषक से प्रेषक को पास करें। मूल कॉल का जवाब देने के लिए प्रतिनिधि gen_server:reply/2 का उपयोग करता है।

एक gen_server का उपयोग करने की यह विधि संभवतः आपके लिए हो सकती है। एक "सादा" प्रक्रिया शुरू करें जिसे आप चुनिंदा प्राप्त करने के लिए प्राप्त-अंत का उपयोग करते हैं। यदि यह वास्तव में स्वतंत्र नौकरी है तो gen_server इसे अनदेखा कर सकता है (आग और भूलना)। यदि यह जानना है कि यह समाप्त हो गया है तो कोई gen_server:cast/2 प्रारंभिक "सादा" प्रक्रिया से इसे एक संदेश वापस कर सकता है।

यदि आप चुनिंदा प्राप्त करते समय gen_server को अवरुद्ध करना चाहते हैं, तो प्रक्रिया को शुरू करने के लिए यह भी एक विचार हो सकता है और लौटने से पहले मरने का इंतजार हो सकता है। चुनिंदा प्राप्तकर्ता ओ ओ (एन) रैखिक संदेश पर आने वाले क्रम में खोजना है। तो प्रत्येक चुनिंदा प्राप्तकर्ता सभी कतारबद्ध संदेशों को स्कैन करेगा जो एक लोकप्रिय gen_server के लिए उच्च हो सकता है।

कोई भी कंपनी केवल वहां मौजूद मालिकों के पास नहीं है। कोई erlang आवेदन केवल gen_servers होने के लिए माना जाता है।

+0

gen_fsm एक दिलचस्प विचार है - मैं इसका उपयोग करने का बहाना ढूंढ रहा हूं। पहले ब्लश पर, मुझे नहीं लगता कि यह मेरे लिए काम करेगा, जब तक कि मैं किसी भी तरह से राज्यों को "पैरामीटर" नहीं कर सकता। ठेठ मामला 8 राज्य है, लेकिन सैकड़ों के साथ बढ़त के मामले हैं। पता नहीं है कि gen_fsm इसका मतलब था या नहीं। मैं वास्तव में, वास्तव में ओटीपी सुविधाओं को चाहता हूं, इसलिए मैं चुनिंदा प्राप्तकर्ता को किसी अन्य तरीके से संभाल दूंगा क्योंकि दिया गया है कि gen_servers स्पष्ट रूप से इसे स्वाभाविक रूप से नहीं कर सकते हैं। – mwt

2

सिर्फ इसलिए कि आप अपने मॉड्यूल में से किसी एक के लिए gen_server का उपयोग नहीं कर सकते हैं इसका मतलब यह नहीं है कि आप ओटीपी का उपयोग नहीं कर रहे हैं। सभी कॉलबैक मॉड्यूल आपके लिए प्राप्त ब्लॉक लागू करते हैं जो आपको चुनिंदा रिसीव का उपयोग करने से रोकता है। ऐसा कोई कारण नहीं है कि आप अपनी खुद की सेवा को लागू नहीं कर सकें जो चुनिंदा प्राप्त करता है। और ऐसा करने का मतलब यह नहीं है कि आपने इसे ओटीपी तरीके से नहीं किया है।

आप अभी भी अपनी सेवा पर्यवेक्षक द्वारा प्रबंधित किए गए सभी लाभों के साथ प्रबंधित कर सकते हैं।

4

नहीं, gen_server को चुनिंदा रिसीव को संभालने में सक्षम होने के लिए डिज़ाइन नहीं किया गया है, प्रत्येक अनुरोध संसाधित होने पर संसाधित होता है। यह वास्तव में एक कठिन समस्या है क्योंकि एर्लांग को यह आवश्यक है कि सभी पैटर्न संकलन समय पर ज्ञात हों, वहां कोई "पैटर्न ऑब्जेक्ट" नहीं है।

मैं मानता हूं कि gen_fsm शायद आपके लिए नहीं है क्योंकि यह राज्यों की संख्या में विस्फोट होने से पहले किसी भी क्रम में आने वाले विभिन्न संदेशों को नहीं ले सकता है। यह चुनिंदा प्राप्तकर्ताओं को जोड़ने के कारणों में से एक था, यह आपको अनचाहे संदेशों को सुरक्षित रूप से अनदेखा करने की अनुमति देता है, जिससे उन्हें बाद में छोड़ दिया जाता है।

कौन सा ओटीपी आप विशेष रूप से रुचि रखते हैं?

+0

यदि आपका मतलब है कि कौन सी ओटीपी विशेषताएं हैं, तो, मुझे डिबगिंग सामान पसंद है, जैसे sys: get_status। यह वास्तव में पहले से ही आसान है। और एसएसएल से आने वाली क्रैश रिपोर्ट अमूल्य रही है। और मैं प्रक्रियाओं की निगरानी करना चाहता हूं, हालांकि शायद यह सामान्य प्रक्रियाओं के साथ इतना आसान है? और मैं थोड़े तरह से मेरी प्रक्रियाओं को gen_server api के साथ कॉल करने का विचार पसंद आया। सबसे बड़ी बात यह है कि यह मेरी पहली बड़ी एरलांग परियोजना है और यह एक समयसीमा पर है और ओटीपी सही तरीके की तरह दिखता है। हर क्रैनी का पता लगाने का समय नहीं है, मैं यह सुनिश्चित करना चाहता हूं कि मैं सभी फायदे में बने रहूं। – mwt

+0

यह कहना है कि, जितना संभव हो सके मैं आवेदन ढांचे के अनुरूप होना चाहता हूं ताकि मैं समझ सकूं कि फायदे क्या हैं। इसके अलावा, मुझे रिलीज अपग्रेड हैंडलिंग अभी तक नहीं मिला है, और मुझे उम्मीद है कि इसके लिए gen_servers का उपयोग करने का लाभ होगा। – mwt

संबंधित मुद्दे