├── requester.rb ├── worker.rb ├── README.md └── broker.coffee /requester.rb: -------------------------------------------------------------------------------- 1 | require 'zmq' 2 | 3 | context = ZMQ::Context.new 4 | req = context.socket ZMQ::REQ 5 | 6 | id = ARGV.shift || :single 7 | 8 | req.setsockopt ZMQ::IDENTITY, "requester-#{id}" 9 | req.connect 'tcp://127.0.0.1:5556' 10 | 11 | begin 12 | loop do 13 | print ">> " 14 | puts msg = gets.strip 15 | 16 | req.send msg 17 | puts "=> #{req.recv}" 18 | end 19 | rescue SignalException 20 | puts 'closing...' 21 | req.close 22 | end 23 | -------------------------------------------------------------------------------- /worker.rb: -------------------------------------------------------------------------------- 1 | require 'zmq' 2 | 3 | context = ZMQ::Context.new 4 | req = context.socket ZMQ::REQ 5 | 6 | id = ARGV.shift || :single 7 | 8 | req.setsockopt ZMQ::IDENTITY, "worker-#{id}" 9 | req.connect 'tcp://127.0.0.1:5555' 10 | 11 | req.send 'ok' 12 | 13 | begin 14 | while requester = req.recv 15 | msg = req.recv 16 | 17 | req.send requester, ZMQ::SNDMORE 18 | req.send "#{msg}!" 19 | puts "Processed #{msg.inspect} for #{requester}" 20 | end 21 | rescue SignalException 22 | puts 'closing...' 23 | req.close 24 | end 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Service Queue 2 | 3 | Experimental zeromq task broker for possible use with GitHub Services. 4 | 5 | The code is pretty hackish and untested still. You can set it up like 6 | this: 7 | 8 | 1. Install zeromq (with homebrew or equivalent). 9 | 2. Install node 0.4.8, npm 1.0.x, and coffee-script. 10 | 3. With npm, install zeromq. 11 | 4. Setup ruby 1.8 or 1.9 with the zeromq gem. 12 | 13 | Start the broker: 14 | 15 | $ coffee broker.coffee 16 | 17 | Start a worker: 18 | 19 | $ ruby worker.rb 20 | 21 | If you want to start multiple workers, give them unique names: 22 | 23 | $ ruby worker.rb 1 24 | $ ruby worker.rb 2 25 | $ ruby worker.rb 3 26 | 27 | Start up a requester to submit a job: 28 | 29 | $ ruby requester.rb 30 | 31 | Like workers, you can start up multiple requesters with unique names: 32 | 33 | $ ruby requester.rb 1 34 | $ ruby requester.rb 2 35 | $ ruby requester.rb 3 36 | 37 | This amazing service will add exclamations to your input! 38 | 39 | >> abc 40 | => abc! 41 | 42 | More to come. 43 | -------------------------------------------------------------------------------- /broker.coffee: -------------------------------------------------------------------------------- 1 | # Binds a Frontend ROUTER socket to 5556. 2 | # Binds a Backend ROUTER socket to 5555. 3 | zmq = require 'zeromq' 4 | closing = false 5 | 6 | # The frontend receives REQ messages from Resque workers requesting a service 7 | # hook is called. 8 | frontend = zmq.createSocket 'router' 9 | requesters = [] 10 | frontend.on 'message', (id, b, msg) -> 11 | console.log "FRONTEND", id.toString(), msg.toString() 12 | requesters.push [id, msg] 13 | run() 14 | 15 | # The backend receives REQ messages from service workers ready to fulfill a 16 | # Hook. 17 | backend = zmq.createSocket 'router' 18 | workers = [] # List of available service workers 19 | backend.on 'message', (env, b, requester, msg) -> 20 | console.log "BACKEND", env.toString(), (msg or requester).toString() 21 | workers.push env 22 | if !msg? 23 | msg = requester 24 | requester = null 25 | if requester? 26 | frontend.send requester, b, msg 27 | run() 28 | 29 | # This is called after every message. Try to match up a Resque hook task with 30 | # a service hook worker. 31 | run = -> 32 | if requesters.length == 0 33 | backend.close() if closing 34 | return 35 | return if workers.length == 0 36 | 37 | requester = requesters.shift() 38 | worker = workers.shift() 39 | 40 | console.log requester[0].toString(), 41 | worker.toString(), requester[1].toString() 42 | backend.send worker, '', requester[0], requester[1] 43 | run() 44 | 45 | frontend.identity = 'broker-frontend' 46 | backend.identity = 'broker-backend' 47 | 48 | frontend.bind 'tcp://127.0.0.1:5556', -> 49 | console.log 'frontend bound' 50 | backend.bind 'tcp://127.0.0.1:5555', -> 51 | console.log 'backend bound' 52 | 53 | process.on 'SIGQUIT', -> 54 | console.log "killing gracefully" 55 | frontend.close() 56 | closing = true 57 | run() 58 | --------------------------------------------------------------------------------