Redis
 sql >> डेटाबेस >  >> NoSQL >> Redis

रेल थ्रेड के भीतर एक चर तक पहुंचना

अंत में अद्यतन संपादन:कार्य कोड दिखाता है। डिबगिंग कोड को छोड़कर मुख्य मॉड्यूल असंशोधित। नोट:समाप्ति से पहले सदस्यता समाप्त करने की आवश्यकता के संबंध में मैंने पहले ही नोट कर ली समस्या का अनुभव किया।

कोड सही दिखता है। मैं देखना चाहता हूं कि आप इसे कैसे चालू कर रहे हैं।

config/application.rb में, शायद आपके पास कम से कम कुछ ऐसा हो:

require 'ws_communication'
config.middleware.use WsCommunication

फिर, आपके जावास्क्रिप्ट क्लाइंट में, आपके पास कुछ ऐसा होना चाहिए:

var ws = new WebSocket(uri);

क्या आप WsCommunication के किसी अन्य उदाहरण को तत्काल करते हैं? यह @clients को एक खाली सरणी में सेट करेगा और आपके लक्षण प्रदर्शित कर सकता है। कुछ इस तरह गलत होगा:

var ws = new WsCommunication;

यह हमारी मदद करेगा यदि आप क्लाइंट को दिखाएंगे और, शायद, config/application.rb अगर यह पोस्ट मदद नहीं करता है।

वैसे, मैं इस टिप्पणी से सहमत हूं कि किसी भी अपडेट पर @clients को म्यूटेक्स द्वारा संरक्षित किया जाना चाहिए, अगर यह भी नहीं पढ़ता है। यह एक गतिशील संरचना है जो किसी भी घटना-संचालित प्रणाली में किसी भी समय बदल सकती है। रेडिस-म्यूटेक्स एक अच्छा विकल्प है। (उम्मीद है कि लिंक सही है क्योंकि जीथब इस समय हर चीज पर 500 त्रुटियां फेंक रहा है।)

आप यह भी नोट कर सकते हैं कि $redis.publish संदेश प्राप्त करने वाले ग्राहकों की संख्या का एक पूर्णांक मान देता है।

अंत में, आप पा सकते हैं कि समाप्ति से पहले आपको यह सुनिश्चित करने की आवश्यकता है कि आपका चैनल सदस्यता समाप्त कर दिया गया है। मेरे पास ऐसी स्थितियां हैं जहां मैंने एक ही चैनल की पिछली सदस्यताओं के कारण प्रत्येक संदेश को एकाधिक, यहां तक ​​​​कि कई बार भेजना समाप्त कर दिया है, जिन्हें साफ़ नहीं किया गया था। चूंकि आप एक थ्रेड के भीतर चैनल की सदस्यता ले रहे हैं, आपको उसी थ्रेड के भीतर सदस्यता समाप्त करने की आवश्यकता होगी या प्रक्रिया सही थ्रेड के जादुई रूप से प्रकट होने की प्रतीक्षा में बस "लटका" जाएगी। मैं "सदस्यता समाप्त" ध्वज सेट करके और फिर एक संदेश भेजकर उस स्थिति को संभालता हूं। फिर, on.message ब्लॉक के भीतर, मैं सदस्यता समाप्त ध्वज के लिए परीक्षण करता हूं और वहां सदस्यता समाप्त करता हूं।

आपके द्वारा प्रदान किया गया मॉड्यूल, केवल मामूली डिबगिंग संशोधनों के साथ:

require 'faye/websocket'
require 'redis'

class WsCommunication
  KEEPALIVE_TIME = 15 #seconds
  CHANNEL = 'vip-deck'

  def initialize(app)
    @app = app
    @clients = []
    uri = URI.parse(ENV['REDISCLOUD_URL'])
    $redis = Redis.new(host: uri.host, port: uri.port, password: uri.password)
    Thread.new do
      redis_sub = Redis.new(host: uri.host, port: uri.port, password: uri.password)
      redis_sub.subscribe(CHANNEL) do |on|
        on.message do |channel, msg|
          puts "Message event. Clients receiving:#{@clients.count};"
          @clients.each { |ws| ws.send(msg) }
        end
      end
    end
  end

  def call(env)
    if Faye::WebSocket.websocket?(env)
      ws = Faye::WebSocket.new(env, nil, {ping: KEEPALIVE_TIME})

      ws.on :open do |event|
        @clients << ws
        puts "Open event. Clients open:#{@clients.count};"
      end

      ws.on :message do |event|
        receivers = $redis.publish(CHANNEL, event.data)
        puts "Message published:#{event.data}; Receivers:#{receivers};"
      end

      ws.on :close do |event|
        @clients.delete(ws)
        puts "Close event. Clients open:#{@clients.count};"
        ws = nil
      end

      ws.rack_response
    else
      @app.call(env)
    end
  end
end

मेरे द्वारा प्रदान किया गया परीक्षण ग्राहक कोड:

# encoding: UTF-8
puts "Starting client-subscriber.rb"
$:.unshift File.expand_path '../lib', File.dirname(__FILE__)
require 'rubygems'
require 'eventmachine'
require 'websocket-client-simple'

puts "websocket-client-simple v#{WebSocket::Client::Simple::VERSION}"

url = ARGV.shift || 'ws://localhost:3000'

EM.run do

  ws = WebSocket::Client::Simple.connect url

  ws.on :message do |msg|
    puts msg
  end

  ws.on :open do
    puts "-- Subscriber open (#{ws.url})"
  end

  ws.on :close do |e|
    puts "-- Subscriber close (#{e.inspect})"
    exit 1
  end

  ws.on :error do |e|
    puts "-- Subscriber error (#{e.inspect})"
  end

end

मेरे द्वारा प्रदान किया गया परीक्षण प्रकाशक कोड। प्रकाशक और सब्सक्राइबर को आसानी से जोड़ा जा सकता है, क्योंकि ये केवल परीक्षण हैं:

# encoding: UTF-8
puts "Starting client-publisher.rb"
$:.unshift File.expand_path '../lib', File.dirname(__FILE__)
require 'rubygems'
require 'eventmachine'
require 'json'
require 'websocket-client-simple'

puts "websocket-client-simple v#{WebSocket::Client::Simple::VERSION}"

url = ARGV.shift || 'ws://localhost:3000'

EM.run do
  count ||= 0
  timer = EventMachine.add_periodic_timer(5+rand(5)) do
    count += 1
    send({"MESSAGE": "COUNT:#{count};"})
  end

  @ws = WebSocket::Client::Simple.connect url

  @ws.on :message do |msg|
    puts msg
  end

  @ws.on :open do
    puts "-- Publisher open"
  end

  @ws.on :close do |e|
    puts "-- Publisher close (#{e.inspect})"
    exit 1
  end

  @ws.on :error do |e|
    puts "-- Publisher error (#{e.inspect})"
    @ws.close
  end

  def self.send message
    payload = message.is_a?(Hash) ? message : {payload: message}
    @ws.send(payload.to_json)
  end
end

एक नमूना config.ru जो रैक मिडलवेयर परत पर यह सब चलाता है:

require './controllers/main'
require './middlewares/ws_communication'
use WsCommunication
run Main.new

यह मुख्य है। मैंने इसे अपने चल रहे संस्करण से हटा दिया है, इसलिए यदि आप इसका उपयोग करते हैं तो इसे ट्वीक करने की आवश्यकता हो सकती है:

%w(rubygems bundler sinatra/base json erb).each { |m| require m }
ENV['RACK_ENV'] ||= 'development'
Bundler.require
$: << File.expand_path('../', __FILE__)
$: << File.expand_path('../lib', __FILE__)

Dir["./lib/*.rb", "./lib/**/*.rb"].each { |file| require file }
env = ENV['OS'] == 'Windows_NT' ? 'development' : ENV['RACK_ENV']

  class Main < Sinatra::Base

    env = ENV['OS'] == 'Windows_NT' ? 'development' : ENV['RACK_ENV']
    get "/" do
      erb :"index.html"
    end

    get "/assets/js/application.js" do
      content_type :js
      @scheme = env == "production" ? "wss://" : "ws://"
      erb :"application.js"
    end
  end


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. रेडिस में रोलबैक के साथ लेनदेन को कैसे कार्यान्वित करें

  2. स्प्रिंग डेटा रेस्ट एप्लिकेशन को रेडिस कैशिंग को लागू करने के बाद डेटाबेस से डेटा नहीं मिल रहा है

  3. क्या मुझे .quit() का उपयोग करके अपना नोड रेडिस क्लाइंट इंस्टेंस छोड़ने की ज़रूरत है?

  4. जावास्क्रिप्ट डिज़ाइन पैटर्न -- अवांछित अतुल्यकालिकता से निपटना

  5. Laravel पर रेडिस पाइपलाइनिंग फ़ंक्शन के बाहर चर को एक्सेस करना