Commits

William Pitcock committed b4b5f00

rpc_client: reuse the socket to batch API calls, improves latency significantly. also use a better reading strategy.

Comments (0)

Files changed (1)

ediarpc/rpc_client.py

         self._secret = secret
         self._allow_untrusted = allow_untrusted
         self._iterations = iterations
+        self._socket = None
 
     def _read_loop(self, sock):
         data = []
-        sock.settimeout(None)
-        data.append(sock.recv(1024))
-        sock.settimeout(0.1)
-
+        end = '}\r\n'
         while True:
             try:
-                data.append(sock.recv(1024))
+                packet = sock.recv(1024)
+                if end in packet:
+                    data.append(packet[:packet.find(end)])
+                    break
+                data.append(packet)
+                if len(data) > 1:
+                    last_pair = data[-2] + data[-1]
+                    if end in last_pair:
+                        data[-2] = last_pair[:last_pair.find(end)]
+                        data.pop()
+                        break
             except:
                 break
+        return ''.join(data).strip() + '}'
+
+    def _connect(self):
+        if self._socket is None:
+            self._socket = socket.create_connection((self._host, self._port))
+
+        return self._socket
+
+    def _close(self):
+        if self._socket is None:
+            self._socket.close()
+
+        self._socket = None
 
-        sock.settimeout(None)
-        return ''.join(data)
+    def __del__(self):
+        self._close()
 
     def _call(self, name, **kwargs):
-        sock = socket.create_connection((self._host, self._port))
+        sock = self._connect()
 
-        envelope = rpc_message.encode(self._secret, name, **kwargs) + '\r\n'
+        envelope = rpc_message.encode(self._secret, name, iterations=self._iterations, **kwargs) + '\r\n'
         sock.sendall(envelope) 
         response = self._read_loop(sock)
-        sock.close()
 
         return rpc_message.decode(self._secret, response, self._allow_untrusted, iterations=self._iterations)[1]