def test_unsubscribe_only_if_max_reached(self): nc = Client() options = { "io_loop": self.io_loop } yield nc.connect(**options) log = Log() sid = yield nc.subscribe("foo", cb=log.persist) yield nc.publish("foo", b'A') yield nc.publish("foo", b'B') yield nc.publish("foo", b'C') yield tornado.gen.sleep(1) self.assertEqual(3, len(log.records["foo"])) yield nc.unsubscribe(sid, 3) yield nc.publish("foo", b'D') yield nc.flush() self.assertEqual(3, len(log.records["foo"])) self.assertEqual(b'A', log.records["foo"][0].data) self.assertEqual(b'B', log.records["foo"][1].data) self.assertEqual(b'C', log.records["foo"][2].data) # Should not exist by now yield tornado.gen.sleep(1) with self.assertRaises(KeyError): nc._subs[sid].received http = tornado.httpclient.AsyncHTTPClient() response = yield http.fetch('http://127.0.0.1:%d/connz' % self.server_pool[0].http_port) result = json.loads(response.body) connz = result['connections'][0] self.assertEqual(0, connz['subscriptions'])
def test_close_connection(self): nc = Client() options = { "dont_randomize": True, "servers": [ "nats://*****:*****@127.0.0.1:4223", "nats://*****:*****@127.0.0.1:4224" ], "io_loop": self.io_loop } yield nc.connect(**options) self.assertEqual(True, nc._server_info["auth_required"]) log = Log() sid_1 = yield nc.subscribe("foo", "", log.persist) self.assertEqual(sid_1, 1) sid_2 = yield nc.subscribe("bar", "", log.persist) self.assertEqual(sid_2, 2) sid_3 = yield nc.subscribe("quux", "", log.persist) self.assertEqual(sid_3, 3) yield nc.publish("foo", "hello") yield tornado.gen.sleep(1.0) # Done yield nc.close() orig_gnatsd = self.server_pool.pop(0) orig_gnatsd.finish() try: a = nc._current_server # Wait and assert that we don't reconnect. yield tornado.gen.sleep(3) finally: b = nc._current_server self.assertEqual(a.uri, b.uri) self.assertFalse(nc.is_connected) self.assertFalse(nc.is_reconnecting) self.assertTrue(nc.is_closed) with(self.assertRaises(ErrConnectionClosed)): yield nc.publish("hello", "world") with(self.assertRaises(ErrConnectionClosed)): yield nc.flush() with(self.assertRaises(ErrConnectionClosed)): yield nc.subscribe("hello", "worker") with(self.assertRaises(ErrConnectionClosed)): yield nc.publish_request("hello", "inbox", "world") with(self.assertRaises(ErrConnectionClosed)): yield nc.request("hello", "world") with(self.assertRaises(ErrConnectionClosed)): yield nc.timed_request("hello", "world")
def test(): client = Client() options = {"servers": ["nats://%s:%d" % (NATS_HOST, NATS_PORT)]} yield client.connect(**options) msg = "0" * size for i in range(0, COUNT): yield client.publish(TOPIC, msg) yield client.publish(TOPIC, "quit") yield client.flush()
def main(): nc = NATS() # Set pool servers in the cluster and give a name to the client. options = { "name": "worker", "servers": [ "nats://*****:*****@127.0.0.1:4222", "nats://*****:*****@127.0.0.1:4223", "nats://*****:*****@127.0.0.1:4224" ] } # Explicitly set loop to use for the reactor. options["io_loop"] = tornado.ioloop.IOLoop.instance() yield nc.connect(**options) @tornado.gen.coroutine def subscriber(msg): yield nc.publish("discover", "pong") yield nc.subscribe("discover", "", subscriber) @tornado.gen.coroutine def async_subscriber(msg): # First request takes longer, while others are still processed. if msg.subject == "requests.1": yield tornado.gen.sleep(0.5) print("Processed request [{0}]: {1}".format(msg.subject, msg)) # Create asynchronous subscription and make roundtrip to server # to ensure that subscriptions have been processed. yield nc.subscribe_async("requests.*", cb=async_subscriber) yield nc.flush() for i in range(1, 10): yield nc.publish("requests.{0}".format(i), "example") yield tornado.gen.sleep(1) while True: # Confirm stats to implement basic throttling logic. sent = nc.stats["out_msgs"] received = nc.stats["in_msgs"] delta = sent - received if delta > 2000: print("Waiting... Sent: {0}, Received: {1}, Delta: {2}".format( sent, received, delta)) yield tornado.gen.sleep(1) if nc.stats["reconnects"] > 10: print("[WARN] Reconnected over 10 times!") for i in range(1000): yield nc.publish("discover", "ping")
def main(): nc = NATS() # Set pool servers in the cluster and give a name to the client. options = { "name": "worker", "servers": [ "nats://*****:*****@127.0.0.1:4222", "nats://*****:*****@127.0.0.1:4223", "nats://*****:*****@127.0.0.1:4224" ] } # Explicitly set loop to use for the reactor. options["io_loop"] = tornado.ioloop.IOLoop.instance() yield nc.connect(**options) @tornado.gen.coroutine def subscriber(msg): yield nc.publish("discover", "pong") yield nc.subscribe("discover", "", subscriber) @tornado.gen.coroutine def async_subscriber(msg): # First request takes longer, while others are still processed. if msg.subject == "requests.1": yield tornado.gen.sleep(0.5) print("Processed request [{0}]: {1}".format(msg.subject, msg)) # Create asynchronous subscription and make roundtrip to server # to ensure that subscriptions have been processed. yield nc.subscribe_async("requests.*", cb=async_subscriber) yield nc.flush() for i in range(1, 10): yield nc.publish("requests.{0}".format(i), "example") yield tornado.gen.sleep(1) while True: # Confirm stats to implement basic throttling logic. sent = nc.stats["out_msgs"] received = nc.stats["in_msgs"] delta = sent - received if delta > 2000: print("Waiting... Sent: {0}, Received: {1}, Delta: {2}".format(sent, received, delta)) yield tornado.gen.sleep(1) if nc.stats["reconnects"] > 10: print("[WARN] Reconnected over 10 times!") for i in range(1000): yield nc.publish("discover", "ping")
class NatsUtils(object): def __init__(self, servers, subject, handle): self.__nc__ = Client() self.__servers__ = servers self.__subject__ = subject self.__handle__ = handle @tornado.gen.coroutine def main(self): yield self.__nc__.connect(self.__servers__) for i in range(0, len(self.__subject__)): yield self.__nc__.subscribe(self.__subject__[i], cb=self.__handle__[i]) def startNats(self): self.main() tornado.ioloop.IOLoop.instance().start() @tornado.gen.coroutine def publish(self, subject, data): yield self.__nc__.publish(subject, data) yield self.__nc__.flush() def isConnect(self): return self.__nc__.is_connected
def test_subscribe_sync(self): nc = Client() msgs = [] @tornado.gen.coroutine def subscription_handler(msg): # Futures for subscription are each processed # in sequence. if msg.subject == "tests.1": yield tornado.gen.sleep(1.0) if msg.subject == "tests.3": yield tornado.gen.sleep(1.0) msgs.append(msg) yield nc.connect(io_loop=self.io_loop) sid = yield nc.subscribe("tests.>", cb=subscription_handler) for i in range(0, 5): yield nc.publish("tests.{0}".format(i), b'bar') # Wait a bit for messages to be received. yield tornado.gen.sleep(4.0) self.assertEqual(5, len(msgs)) self.assertEqual("tests.1", msgs[1].subject) self.assertEqual("tests.3", msgs[3].subject) yield nc.close()
def main(): nc = NATS() # Establish connection to the server. options = {"verbose": True, "servers": ["nats://127.0.0.1:4222"]} yield nc.connect(**options) def discover(msg=None): channel_message = message_pb2.ChannelMessage() channel_message.ParseFromString(msg.data) print("[Received]: %s" % channel_message) send_message = message_pb2.ChannelMessage() send_message.chan_num = 5 #send_message.from = "python" send_message.message = "Hello, World!" sid = yield nc.subscribe("world.channel_message", "", discover) yield nc.publish("world.channel_message", send_message.SerializeToString()) loop = tornado.ioloop.IOLoop.instance() yield tornado.gen.Task(loop.add_timeout, time.time() + 20) try: start = datetime.now() # Make roundtrip to the server and timeout after 1 second yield nc.flush(1) end = datetime.now() print("Latency: %d µs" % (end.microsecond - start.microsecond)) except tornado.gen.TimeoutError, e: print("Timeout! Roundtrip too slow...")
def test_subscribe_async(self): nc = Client() msgs = [] @tornado.gen.coroutine def subscription_handler(msg): # Callback dispatched asynchronously and a coroutine # so it does not block. if msg.subject == "tests.1": yield tornado.gen.sleep(0.5) if msg.subject == "tests.3": yield tornado.gen.sleep(0.2) msgs.append(msg) yield nc.connect(io_loop=self.io_loop) sid = yield nc.subscribe_async("tests.>", cb=subscription_handler) for i in range(0, 5): yield nc.publish("tests.{0}".format(i), b'bar') # Wait a bit for messages to be received. yield tornado.gen.sleep(4.0) self.assertEqual(5, len(msgs)) self.assertEqual("tests.1", msgs[4].subject) self.assertEqual("tests.3", msgs[3].subject) yield nc.close()
def test_publish(self): nc = Client() yield nc.connect(io_loop=self.io_loop) self.assertEqual(Client.CONNECTED, nc._status) info_keys = nc._server_info.keys() self.assertTrue(len(info_keys) > 0) log = Log() yield nc.subscribe(">", "", log.persist) yield nc.publish("one", "hello") yield nc.publish("two", "world") yield tornado.gen.sleep(1.0) http = tornado.httpclient.AsyncHTTPClient() response = yield http.fetch('http://127.0.0.1:%d/varz' % self.server_pool[0].http_port) varz = json.loads(response.body) self.assertEqual(10, varz['in_bytes']) self.assertEqual(10, varz['out_bytes']) self.assertEqual(2, varz['in_msgs']) self.assertEqual(2, varz['out_msgs']) self.assertEqual(2, len(log.records.keys())) self.assertEqual("hello", log.records['one'][0].data) self.assertEqual("world", log.records['two'][0].data) self.assertEqual(10, nc.stats['in_bytes']) self.assertEqual(10, nc.stats['out_bytes']) self.assertEqual(2, nc.stats['in_msgs']) self.assertEqual(2, nc.stats['out_msgs'])
def test_publish_max_payload(self): nc = Client() yield nc.connect(io_loop=self.io_loop) self.assertEqual(Client.CONNECTED, nc._status) info_keys = nc._server_info.keys() self.assertTrue(len(info_keys) > 0) with self.assertRaises(ErrMaxPayload): yield nc.publish("large-message", "A" * (nc._server_info["max_payload"] * 2))
def notify_new_user(user, config): client = Nats() server = 'nats://{}:{}'.format(config['host'], config['port']) opts = {"servers": [server]} yield client.connect(**opts) notif = { 'message': 'created', 'user_name': '{0}'.format(user.name), 'user_id': '{0}'.format(user.user_id) } yield client.publish('userAction', json.dumps(notif)) yield client.flush() log.info("New user notification sent on NATS for {0}".format(user.user_id))
def notify_new_user(user, config): client = Nats() server = 'nats://{}:{}'.format(config['host'], config['port']) opts = {"servers": [server]} yield client.connect(**opts) notif = { 'message': 'created', 'user_name': '{0}'.format(user.name), 'user_id': '{0}'.format(user.user_id) } yield client.publish('userAction', json.dumps(notif)) yield client.flush() log.info("New user notification sent on NATS for {0}".format(user.user_id))
def main(): nc = NATS() yield nc.connect("demo.nats.io") @tornado.gen.coroutine def subscriber(msg): print("Msg received on [{0}]: {1}".format(msg.subject, msg.data)) yield nc.subscribe("foo.*.baz", "", subscriber) yield nc.subscribe("foo.bar.*", "", subscriber) yield nc.subscribe("foo.>", "", subscriber) yield nc.subscribe(">", "", subscriber) # Matches all of above yield nc.publish("foo.bar.baz", b"Hello World") yield tornado.gen.sleep(1)
def test_subscribe_async_non_coro(self): nc = Client() msgs = [] def subscription_handler(msg): # Dispatched asynchronously but would be received in sequence... msgs.append(msg) yield nc.connect(io_loop=self.io_loop) sid = yield nc.subscribe_async("tests.>", cb=subscription_handler) for i in range(0, 5): yield nc.publish("tests.{0}".format(i), b'bar') # Wait a bit for messages to be received. yield tornado.gen.sleep(4.0) self.assertEqual(5, len(msgs)) self.assertEqual("tests.1", msgs[1].subject) self.assertEqual("tests.3", msgs[3].subject) yield nc.close()
def test_subscribe_sync_non_coro(self): nc = Client() msgs = [] def subscription_handler(msg): # Callback blocks so dispatched in sequence. if msg.subject == "tests.1": time.sleep(0.5) if msg.subject == "tests.3": time.sleep(0.2) msgs.append(msg) yield nc.connect(io_loop=self.io_loop) sid = yield nc.subscribe("tests.>", cb=subscription_handler) for i in range(0, 5): yield nc.publish("tests.{0}".format(i), b'bar') # Wait a bit for messages to be received. yield tornado.gen.sleep(4.0) self.assertEqual(5, len(msgs)) self.assertEqual("tests.1", msgs[1].subject) self.assertEqual("tests.3", msgs[3].subject) yield nc.close()
def test_auth_connect_fails(self): class Component: def __init__(self, nc): self.nc = nc self.error = None self.error_cb_called = False self.close_cb_called = False self.disconnected_cb_called = False self.reconnected_cb_called = False def error_cb(self, err): self.error = err self.error_cb_called = True def close_cb(self): self.close_cb_called = True def disconnected_cb(self): self.disconnected_cb_called = True def reconnected_cb(self): self.reconnected_cb_called = True nc = Client() component = Component(nc) options = { "dont_randomize": True, "servers": [ "nats://*****:*****@127.0.0.1:4223", "nats://*****:*****@127.0.0.1:4224" ], "io_loop": self.io_loop, "close_cb": component.close_cb, "error_cb": component.error_cb, "disconnected_cb": component.disconnected_cb, "reconnected_cb": component.reconnected_cb } yield component.nc.connect(**options) self.assertEqual(True, component.nc.is_connected) self.assertEqual(True, nc._server_info["auth_required"]) log = Log() sid_1 = yield component.nc.subscribe("foo", "", log.persist) self.assertEqual(sid_1, 1) sid_2 = yield component.nc.subscribe("bar", "", log.persist) self.assertEqual(sid_2, 2) sid_3 = yield component.nc.subscribe("quux", "", log.persist) self.assertEqual(sid_3, 3) yield nc.publish("foo", "hello") yield tornado.gen.sleep(1) self.assertEqual("hello", log.records['foo'][0].data) yield tornado.gen.sleep(1.0) http = tornado.httpclient.AsyncHTTPClient() response = yield http.fetch('http://127.0.0.1:8223/connz') result = json.loads(response.body) connz = result['connections'][0] self.assertEqual(3, connz['subscriptions']) self.assertEqual(1, connz['in_msgs']) self.assertEqual(5, connz['in_bytes']) yield component.nc.publish("foo", "world") yield tornado.gen.sleep(0.5) response = yield http.fetch('http://127.0.0.1:8223/connz') result = json.loads(response.body) connz = result['connections'][0] self.assertEqual(3, connz['subscriptions']) self.assertEqual(2, connz['in_msgs']) self.assertEqual(10, connz['in_bytes']) orig_gnatsd = self.server_pool.pop(0) orig_gnatsd.finish() # Wait for reconnect logic kick in and fail due to authorization error. yield tornado.gen.sleep(5) self.assertFalse(component.nc.is_connected) self.assertTrue(component.nc.is_reconnecting) # No guarantee in getting the error before the connection is closed, # by the server though the behavior should be as below. # self.assertEqual(1, component.nc.stats['errors_received']) # self.assertEqual(ErrAuthorization, component.nc.last_error()) # self.assertTrue(component.error_cb_called) self.assertTrue(component.disconnected_cb_called) self.assertTrue(component.reconnected_cb_called)
def test_auth_connect(self): nc = Client() options = { "dont_randomize": True, "servers": [ "nats://*****:*****@127.0.0.1:4223", "nats://*****:*****@127.0.0.1:4224" ], "io_loop": self.io_loop } yield nc.connect(**options) self.assertEqual(True, nc._server_info["auth_required"]) log = Log() sid_1 = yield nc.subscribe("foo", "", log.persist) self.assertEqual(sid_1, 1) sid_2 = yield nc.subscribe("bar", "", log.persist) self.assertEqual(sid_2, 2) sid_3 = yield nc.subscribe("quux", "", log.persist) self.assertEqual(sid_3, 3) yield nc.publish("foo", "hello") yield tornado.gen.sleep(1.0) http = tornado.httpclient.AsyncHTTPClient() response = yield http.fetch('http://127.0.0.1:8223/connz') result = json.loads(response.body) connz = result['connections'][0] self.assertEqual(3, connz['subscriptions']) self.assertEqual(1, connz['in_msgs']) self.assertEqual(5, connz['in_bytes']) yield nc.publish("foo", "world") yield tornado.gen.sleep(0.5) response = yield http.fetch('http://127.0.0.1:8223/connz') result = json.loads(response.body) connz = result['connections'][0] self.assertEqual(3, connz['subscriptions']) self.assertEqual(2, connz['in_msgs']) self.assertEqual(10, connz['in_bytes']) orig_gnatsd = self.server_pool.pop(0) orig_gnatsd.finish() try: a = nc._current_server # Wait for reconnect logic kick in... yield tornado.gen.sleep(5) finally: b = nc._current_server self.assertNotEqual(a.uri, b.uri) self.assertTrue(nc.is_connected) self.assertFalse(nc.is_reconnecting) http = tornado.httpclient.AsyncHTTPClient() response = yield http.fetch('http://127.0.0.1:8224/connz') result = json.loads(response.body) connz = result['connections'][0] self.assertEqual(3, connz['subscriptions']) self.assertEqual(0, connz['in_msgs']) self.assertEqual(0, connz['in_bytes']) yield nc.publish("foo", "!!!") yield tornado.gen.sleep(0.5) response = yield http.fetch('http://127.0.0.1:8224/connz') result = json.loads(response.body) connz = result['connections'][0] self.assertEqual(3, connz['subscriptions']) self.assertEqual(1, connz['in_msgs']) self.assertEqual(3, connz['in_bytes']) full_msg = '' for msg in log.records['foo']: full_msg += msg.data self.assertEqual('helloworld!!!', full_msg)