Class: Mongrel2::Connection

Inherits:
Object
  • Object
show all
Extended by:
Loggability
Defined in:
lib/mongrel2/connection.rb

Overview

The Mongrel2 connection class. Connection objects serve as a front end for the ZMQ sockets which talk to the mongrel2 server/s for your handler. It receives TNetString requests and wraps Mongrel2::Request objects around them, and then encodes and sends Mongrel2::Response objects back to the server.

References

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app_id, sub_addr, pub_addr) ⇒ Connection

Create a new Connection identified by app_id (a UUID or other unique string) that will connect to a Mongrel2 server on the sub_addr and pub_addr (e.g., ‘tcp://127.0.0.1:9998’).



30
31
32
33
34
35
36
37
38
39
# File 'lib/mongrel2/connection.rb', line 30

def initialize( app_id, sub_addr, pub_addr )
  @app_id       = app_id
  @sub_addr     = sub_addr
  @pub_addr     = pub_addr

  @request_sock = @response_sock = nil

  @identifier   = make_identifier( app_id )
  @closed       = false
end

Instance Attribute Details

#app_idObject (readonly)

The application’s identifier string that associates it with its route



55
56
57
# File 'lib/mongrel2/connection.rb', line 55

def app_id
  @app_id
end

#identifierObject (readonly)

The ZMQ socket identity used by this connection



58
59
60
# File 'lib/mongrel2/connection.rb', line 58

def identifier
  @identifier
end

#pub_addrObject (readonly)

The connection’s publication (response) socket address



64
65
66
# File 'lib/mongrel2/connection.rb', line 64

def pub_addr
  @pub_addr
end

#sub_addrObject (readonly)

The connection’s subscription (request) socket address



61
62
63
# File 'lib/mongrel2/connection.rb', line 61

def sub_addr
  @sub_addr
end

Instance Method Details

#broadcast(sender_id, conn_ids, data) ⇒ Object

Send the given data to one or more connected clients identified by client_ids via the server specified by sender_id. The client_ids should be an Array of Integer IDs no longer than Mongrel2::MAX_IDENTS.



157
158
159
160
# File 'lib/mongrel2/connection.rb', line 157

def broadcast( sender_id, conn_ids, data )
  idlist = conn_ids.flatten.map( &:to_s ).join( ' ' )
  self.send( sender_id, idlist, data )
end

#broadcast_close(sender_id, *conn_ids) ⇒ Object

Tell the server associated with sender_id to close the connections associated with conn_ids.



189
190
191
# File 'lib/mongrel2/connection.rb', line 189

def broadcast_close( sender_id, *conn_ids )
  self.broadcast( sender_id, conn_ids.flatten, '' )
end

#broadcast_extended(sender_id, conn_ids, response_type, *data) ⇒ Object

Send the given data to one or more connected clients identified by client_ids via the server specified by sender_id as an extended reply of type response_type. The client_ids should be an Array of Integer IDs no longer than Mongrel2::MAX_IDENTS.



167
168
169
170
# File 'lib/mongrel2/connection.rb', line 167

def broadcast_extended( sender_id, conn_ids, response_type, *data )
  idlist = conn_ids.flatten.map( &:to_s ).join( ' ' )
  self.send_extended( sender_id, idlist, response_type, *data )
end

#closeObject

Close both of the sockets and mark the Connection as closed.



195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/mongrel2/connection.rb', line 195

def close
  return if self.closed?
  self.closed = true
  if @request_sock
    @request_sock.options.linger = 0
    @request_sock.close
  end
  if @response_sock
    @response_sock.options.linger = 0
    @response_sock.close
  end
end

#closed?Boolean

Returns true if the connection to the Mongrel2 server has been closed.

Returns:

  • (Boolean)


210
211
212
# File 'lib/mongrel2/connection.rb', line 210

def closed?
  return @closed
end

#connectObject

Establish both connections to the Mongrel2 server.



68
69
70
71
72
73
74
75
76
# File 'lib/mongrel2/connection.rb', line 68

def connect
  self.log.info "Connecting PULL request socket (%s)" % [ self.sub_addr ]
  @request_sock = CZTop::Socket::PULL.new
  @request_sock.connect( self.sub_addr )

  self.log.info "Connecting PUB response socket (%s)" % [ self.pub_addr ]
  @response_sock = CZTop::Socket::PUB.new
  @response_sock.connect( self.pub_addr )
end

#initialize_copy(original) ⇒ Object

Copy constructor – don’t keep the original‘s sockets or closed state.



43
44
45
46
# File 'lib/mongrel2/connection.rb', line 43

def initialize_copy( original )
  @request_sock = @response_sock = nil
  @closed = false
end

#inspectObject

Returns a string containing a human-readable representation of the Connection, suitable for debugging.



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/mongrel2/connection.rb', line 227

def inspect
  state = if @request_sock
    if self.closed?
      "closed"
    else
      "connected"
    end
  else
    "not connected"
  end

  return "#<%p:0x%016x %s (%s)>" % [
    self.class,
    self.object_id * 2,
    self.to_s,
    state,
  ]
end

#receiveObject

Fetch the next request from the server as a Mongrel2::Request object.



110
111
112
113
114
# File 'lib/mongrel2/connection.rb', line 110

def receive
  raw_req = self.recv
  self.log.debug "Receive: parsing raw request: %d bytes" % [ raw_req.bytesize ]
  return Mongrel2::Request.parse( raw_req )
end

#recvObject

Fetch the next request from the server as raw TNetString data.



98
99
100
101
102
103
104
105
106
# File 'lib/mongrel2/connection.rb', line 98

def recv
  self.check_closed

  self.log.debug "Fetching next request (PULL)"
  message = self.request_sock.receive
  data = message.pop
  self.log.debug "  got %d bytes of %s request data" % [ data.bytesize, data.encoding.name ]
  return data
end

#reply(response) ⇒ Object

Write the specified response (Mongrel::Response object) to the requester.



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/mongrel2/connection.rb', line 141

def reply( response )
  response.each_chunk do |data|
    self.send( response.sender_id, response.conn_id, data )
  end
  if response.extended_reply?
    self.log.debug "Response also includes an extended reply."
    data = response.extended_reply_data
    filter = response.extended_reply_filter
    self.send_extended( response.sender_id, response.conn_id, filter, *data )
  end
end

#reply_close(request_or_response) ⇒ Object

Tell the server to close the connection associated with the given request_or_response.



182
183
184
# File 'lib/mongrel2/connection.rb', line 182

def reply_close( request_or_response )
  self.send_close( request_or_response.sender_id, request_or_response.conn_id )
end

#request_sockObject

Fetch the ZMQ::PULL socket for incoming requests, establishing the connection to Mongrel if it hasn’t been already.



81
82
83
84
85
# File 'lib/mongrel2/connection.rb', line 81

def request_sock
  self.check_closed
  self.connect unless @request_sock
  return @request_sock
end

#response_sockObject

Fetch the ZMQ::PUB socket for outgoing responses, establishing the connection to Mongrel if it hasn’t been already.



90
91
92
93
94
# File 'lib/mongrel2/connection.rb', line 90

def response_sock
  self.check_closed
  self.connect unless @response_sock
  return @response_sock
end

#send(sender_id, conn_id, data) ⇒ Object

Write raw data to the given connection ID (conn_id) at the given sender_id.



118
119
120
121
122
123
124
125
# File 'lib/mongrel2/connection.rb', line 118

def send( sender_id, conn_id, data )
  self.check_closed
  header = "%s %d:%s," % [ sender_id, conn_id.to_s.length, conn_id ]
  buf = header + ' ' + data
  self.log.debug "Sending response (PUB)"
  self.response_sock << buf
  self.log.debug "  done with send (%d bytes)" % [ buf.bytesize ]
end

#send_close(sender_id, conn_id) ⇒ Object

Tell the server to close the connection associated with the given sender_id and conn_id.



175
176
177
178
# File 'lib/mongrel2/connection.rb', line 175

def send_close( sender_id, conn_id )
  self.log.info "Sending kill message to connection %d" % [ conn_id ]
  self.send( sender_id, conn_id, '' )
end

#send_extended(sender_id, conn_id, response_type, *data) ⇒ Object

Write raw data to the given connection ID (conn_id) at the specified sender_id as an extended response of type response_type.



130
131
132
133
134
135
136
137
# File 'lib/mongrel2/connection.rb', line 130

def send_extended( sender_id, conn_id, response_type, *data )
  self.check_closed
  self.log.debug "Sending response with %s extended reply (PUB)"
  header = "%s %d:X %s," % [ sender_id, conn_id.to_s.length + 2, conn_id ]
  buf = header + ' ' + TNetstring.dump( [response_type] + data )
  self.response_sock << buf
  self.log.debug "  done with send (%d bytes)" % [ buf.bytesize ]
end

#to_sObject

Return a string describing the connection.



216
217
218
219
220
221
222
# File 'lib/mongrel2/connection.rb', line 216

def to_s
  return "{%s} %s <-> %s" % [
    self.app_id,
    self.sub_addr,
    self.pub_addr,
  ]
end