2013-01-24 18 views
5

मैं एक ऐसी सेवा तैयार कर रहा हूं जो मूल रूप से उपयोगकर्ताओं को बॉट के साथ चैट करने की अनुमति देता है, और बॉट उपयोगकर्ता द्वारा भेजे गए चैट के साथ कुछ अजीब प्रसंस्करण करता है, और अंततः कुछ सार्थक डेटा के साथ जवाब देता है। मूल रूप से कुछ ऐसा कैसे होता है जैसे आर्डवर्र्क ने काम करने के लिए (?) का उपयोग किया।पृष्ठभूमि में रेल + एक्सएमपीपी बॉट

मेरे पास बॉट काम कर रहा है, और अभी सुन रहा है, और मेरे पास एक अलग रेल ऐप है जो अन्य सभी भारी उठाने वाला होगा। ये दोनों भाग अलग-अलग काम कर रहे हैं, और अब मैं दोनों को इंटरफेस करने पर फंस गया हूं। मेरा विचार है कि रॉट के माध्यम से रेल ऐप के साथ बॉट (जो मूल रूप से एक छोटी रूबी स्क्रिप्ट है) को इंटरफ़ेस करना है - जो कुछ भी आता है वह कतार में जाता है, उठाया जाता है, और उसके बाद परिणाम फिर से कतार में धकेल जाते हैं, और फिर स्क्रिप्ट परिणाम के साथ जवाब देंगे।

मैं कैसे इस इंटरफेस स्थापित करने के लिए के रूप में बहुत स्पष्ट नहीं कर रहा हूँ: अगर मैं यह रेक के बिना चलने

  1. मैं/बंद शुरू करने के लिए एक रेक कार्य लिखने की ज़रूरत है/बोट
  2. को फिर से लोड (माना जाता है कि मोनीट द्वारा निगरानी की गई एक स्वतंत्र प्रक्रिया के रूप में) तो मैं Resque के साथ कैसे इंटरफ़ेस कर सकता हूं या अपने रेल मॉडल का उपयोग कैसे कर सकता हूं?

मुझे पता है कि ये बहुत ही मामूली प्रश्न हो सकते हैं, लेकिन मुझे मुश्किल समय समझ रहा है जो बेहतर काम करता है, और सेटअप कैसे प्राप्त करें।

+0

प्रारंभिक/बोट की रोक एक अलग चिंता का विषय है। मोनीट फॉरमैन (https://github.com/ddollar/foreman) जैसे टूल के रूप में एक विकल्प है। मेरे लिए असली सवाल यह है कि क्या आपको अपने रूबी ऐप के साथ अतुल्यकालिक या सिंक्रनाइज़ेशन के साथ काम की आवश्यकता है। यदि आप सिंक इंटरफ़ेस से दूर हो सकते हैं, तो आपका बॉट रेल ऐप पर HTTP कॉल कर सकता है और जीवन सरल है। :) –

उत्तर

4

आपके रेल एप्लिकेशन और इस बोट डेमॉन के बीच संवाद की तीन तरीके हैं:

  1. एक HTTP अनुरोध के रूप में रेल एप्लिकेशन बुला द्वारा (धक्का/रेल ऐप का डेटा खींच)
  2. के साथ सीधे बातचीत करके एक डेटाबेस रेल एप्लिकेशन का उपयोग करता है (संभावना mysql/Postgres)
  3. एक Resque काम कतार प्रणाली के साथ बातचीत करके, Redis डेटाबेस

जब आप enqueuing कर रहे हैं और ResQ खींच द्वारा समर्थित विभिन्न नौकरी कतारों से नौकरियों के कारण, आप एक एपीआई के माध्यम से साझा रेडिस डेटाबेस को पढ़ रहे/लिख रहे हैं। बॉट और रेल ऐप दोनों नेटवर्क पर रेडिस डीबी से बात करते हैं।

मैं बॉट को सीधे रूबी प्रक्रिया या राक्षस द्वारा प्रबंधित राक कार्य के रूप में चलाने की सलाह देता हूं। ऐसा लगता है जैसे आप पहले ही जानते हैं कि यह कैसे करें।

2

मुझे लगता है कि यहां मुख्य मुद्दे यह है कि आपको रेज को झुकाव करने की कोशिश करने के बजाय मैसेजिंग (आईपीसी की तरह, आईएम नहीं) के लिए एक और समाधान की आवश्यकता है जो कि "बस" कतार है। कुछ विकल्प amqp gem (एएमक्यूपी प्रोटोकॉल) या zmq gem (ज़ीरोएमक्यू प्रोटोकॉल) हैं, लेकिन आप रूबी मानक लाइब्रेरी सॉकेट क्लास (good examples) के माध्यम से सादे पुराने यूनिक्स सॉकेट का भी उपयोग कर सकते हैं। उनके पास अलग-अलग पेशेवर और विपक्ष हैं, इसलिए शायद यह आपके ऊपर है।

फिर, बातचीत कुछ इस तरह दिखाई देंगे:

  1. बॉट शुरू होता है।
  2. बीओटी आईपीसी संदेशों के लिए सुनना शुरू कर देता है।
  3. बॉट प्रेषक से एक प्रश्न प्राप्त करता है (एक्सएमपीपी के माध्यम से)।
  4. बॉट रेज्यू के माध्यम से नौकरी कतार देता है।
  5. जॉब HTTP के माध्यम से रेल ऐप को कॉल करता है।
  6. रेल ऐप अपने काम का हिस्सा करता है।
  7. किसी ने या कुछ का समाधान करता है जो कुछ भी क्वेरी था और रेल एप्लिकेशन के माध्यम से एक परिणाम के प्रवेश करती है।
  8. रेल एप्लिकेशन बॉट के लिए कुछ भारतीय दंड संहिता विधि का उपयोग कर परिणाम भेजता है।
  9. बॉट (XMPP) के माध्यम से मूल प्रेषक को परिणाम भेजता है।

हमेशा की तरह कुछ बदलाव हो सकता है। उदाहरण के लिए, मुझे लगता है कि आपको Resque की आवश्यकता नहीं है। बॉट बस रेल एप्लिकेशन को तुरंत अनुरोध पारित कर सकते हैं, लेकिन यह लोड पर निर्भर करता है, समय आप परिणाम और उसके बाद काम पर लौटने के लिए हो सकता है कि Resque काम रेल अनुप्रयोग के लिए इंतजार कर सकते हैं प्राप्त करने के लिए, आप वर्तमान वास्तुकला, आदि चाहते हैं प्रतिक्रिया करने के लिए (रेल ऐप नहीं) आईपीसी का उपयोग करेगा। अन्य विभिन्नताएँ हैं ...

मैं/बंद शुरू करने के लिए एक रेक कार्य लिखने की ज़रूरत है/बोट

को फिर से लोड नहीं, आप ऐसा नहीं करते। यह आप पर निर्भर करता है कि आप इसे कब और कब चलाते हैं। आखिरकार, रेक को कई रूबी स्क्रिप्ट को एक साथ रखने और उनके बीच निर्भरता बनाने के सुविधाजनक तरीके के रूप में देखा जा सकता है। यदि आपको लगता है कि बस इसे चलाने से कुछ अन्य कार्य होंगे (कुछ सफाई, तैनाती, इत्यादि), तो सुविधा के लिए रेक का उपयोग करना अच्छा होगा। यदि पहले से नहीं है, कक्षा में बॉट के तर्क को दोबारा दोहराएं और इसे प्रारंभ करने के लिए रेक कार्य का उपयोग करें। लेकिन अगर आप इसे छोड़ देते हैं और बस अपनी स्क्रिप्ट को चलाते हैं तो यह ठीक होगा (मॉनीट का उपयोग करके, आपकी कस्टम init.d स्क्रिप्ट, एड-हाक इत्यादि)।

यदि मैं बिना रेक के इसे चलाता हूं (माना जाता है कि मोनीट द्वारा निगरानी की गई एक स्वतंत्र प्रक्रिया के रूप में) तो मैं Resque के साथ कैसे इंटरफ़ेस कर सकता हूं या अपने रेल मॉडल तक पहुंच सकता हूं?

रैक नहीं है इस पर प्रभावित करते हैं। ओएस परिप्रेक्ष्य से, यदि आप रेक के माध्यम से रेक या रेक के माध्यम से अपने स्टैंड को एक स्टैंडअलोन स्क्रिप्ट के रूप में चलाते हैं, तो इससे कोई फर्क नहीं पड़ता, वे वैसे भी अलग-अलग प्रक्रियाएं करेंगे। यह भी ध्यान रखें कि रेस्क को रेडिस को कहीं चलने की जरूरत है।

मैं ये बहुत तुच्छ सवाल

नहीं सब पर हो सकता है पता है। मुझे लगता है कि मुद्दों से पहले कुछ समय लगेगा जैसे कि तुच्छ माना जा सकता है।

0

आप अपना कोड प्रारंभकर्ता पर चलाने के लिए डाल सकते हैं और अपने सभी रेल मॉडल या libs तक पूर्ण पहुंच प्राप्त कर सकते हैं।

इस तरह, आपको अपने बॉट और अपने रेल ऐप के बीच "संवाद" करने की आवश्यकता नहीं है, क्योंकि आपका बॉट आपके रेल ऐप के अंदर है।

बॉयलरप्लेट कोड होगा जैसे:

config/initializers/background_app_tasks.rb

class BackgroundWorker 

     #------------------------------- 
     def initialize(operation='normal') 
     @exit = false 
     @lock = Mutex.new # For thread safety 
     @thread = nil 
     say "Starting in '#{operation}' mode..." 
     case operation 
      when 'normal' 
      @thread = Thread.new() { loopme  } 
      when 'cleanup' 
      @thread = Thread.new() { cleanup  } 
      when 'nothing' 
      #startup without threads 
     end 
     @thread.run if @thread 
     end 

     #------------------------------- 
     def exit! 
     begin 
      return if @exit # #stop? 
      say "Exiting #{}, waiting for mutex..." 
      @lock.synchronize { 
       say "exiting thread #{@thread.to_s || '<sem nome>' }..." 
       @exit = true # #stop 
      } 
     rescue Exception => e 
      exceptme(e) 
     end 
     end 

     #------------------------------- 
     def loopme 

     at_exit { exit! } 
     i=0; ok=false; 

     nap = 30 

     while true do 
      begin 
       break if @exit 
       i+=1 

       #lock mutex for processing... 
       @lock.synchronize { 

        #.... do some work .... 

       } 
      rescue StandardError => e 

       #.... 

      end 

      sleep(nap) 
     end 
     end 

end #class 

# ------ M A I N -------- 

Thread.abort_on_exception=false 
e = BackgroundWorker.new(OPERATION) 
संबंधित मुद्दे