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_request(self): nc = Client() yield nc.connect(io_loop=self.io_loop) class Component: def __init__(self, nc): self.nc = nc self.replies = [] @tornado.gen.coroutine def receive_responses(self, msg=None): self.replies.append(msg) @tornado.gen.coroutine def respond(self, msg=None): yield self.nc.publish(msg.reply, "ok:1") yield self.nc.publish(msg.reply, "ok:2") yield self.nc.publish(msg.reply, "ok:3") log = Log() c = Component(nc) yield nc.subscribe(">", "", log.persist) yield nc.subscribe("help", "", c.respond) yield nc.request("help", "please", expected=2, cb=c.receive_responses) yield tornado.gen.sleep(0.5) 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(18, varz['in_bytes']) self.assertEqual(32, varz['out_bytes']) self.assertEqual(4, varz['in_msgs']) self.assertEqual(7, varz['out_msgs']) self.assertEqual(2, len(log.records.keys())) self.assertEqual("please", log.records['help'][0].data) self.assertEqual(2, len(c.replies)) self.assertEqual(32, nc.stats['in_bytes']) self.assertEqual(18, nc.stats['out_bytes']) self.assertEqual(7, nc.stats['in_msgs']) self.assertEqual(4, nc.stats['out_msgs']) full_msg = '' for msg in log.records['help']: full_msg += msg.data self.assertEqual('please', full_msg) self.assertEqual("ok:1", c.replies[0].data) self.assertEqual("ok:2", c.replies[1].data)
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_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 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'])
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 main(): nc = NATS() options = { "verbose": True, "servers": [ ConfigurationManager.ConfigurationManager().getMessageUandPwd() + "@" + ConfigurationManager.ConfigurationManager().getMessageBrokerUrl() + ":" + str(ConfigurationManager.ConfigurationManager(). getMessageBrokerPort()) ] } yield nc.connect(**options) def subscribeMatchServer(msg): matchingExec.handleMatchingMessage(json.loads(msg.data)) yield nc.subscribe(matchingExec.getChannelName(), "job.workers", subscribeMatchServer) matchingExec.logEvent( -1, "INFO", "item-matcher-worker.main", "Started tornado listener on " + matchingExec.getChannelName() + " channel.") matchingExec.logEvent( -1, "INFO", "item-matcher-worker.main", "template-merger on " + TEMPLATE_MERGER_CHANNEL + " channel.") messageSender = MessageSender.MessageSender( matchingExec.configCacheHandler.getMessageBrokerUrl(), matchingExec.configCacheHandler.getMessageBrokerPort(), matchingExec.configCacheHandler.getChannelName()) messageSender.sendMessageAsync( messageSender.createMessageJson("SUBSCRIBE", -1, matchingExec.getChannelName(), {}))
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 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 main(): logging.info("Connecting to NATS") server = "nats://%s:%d" % (natsIPAddress, natsPort) servers = [] servers.append(server) opts = {"verbose": True, "servers": servers} nc = NATS() yield nc.connect(**opts) yield nc.subscribe(natsSubTopic, "", on_message)
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")
def key_handler(config): """NATS handler for discover_key events.""" client = Nats() server = 'nats://{}:{}'.format(config['host'], config['port']) servers = [server] opts = {"servers": servers} yield client.connect(**opts) # create and register subscriber(s) key_subscriber = subscribers.KeyAction(client) future = client.subscribe("keyAction", "keyQueue", key_subscriber.handler) log.info("nats subscription started for keyAction") future.result()
def contact_update_handler(config): """NATS handler for contact update events.""" client = Nats() server = 'nats://{}:{}'.format(config['host'], config['port']) servers = [server] opts = {"servers": servers} yield client.connect(**opts) # create and register subscriber(s) contact_subscriber = subscribers.ContactAction(client) future = client.subscribe("contactAction", "contactQueue", contact_subscriber.handler) log.info("nats subscription started for contactAction") future.result()
def inbound_handler(config): """Inbound message NATS handler.""" client = Nats() server = 'nats://{}:{}'.format(config['host'], config['port']) servers = [server] opts = {"servers": servers} yield client.connect(**opts) # create and register subscriber(s) inbound_email_sub = subscribers.InboundEmail(client) future = client.subscribe("inboundSMTP", "SMTPqueue", inbound_email_sub.handler) log.info("nats subscription started for inboundSMTP") future.result()
def inbound_twitter_handler(config): """Inbound twitterDM NATS handler""" client = Nats() server = 'nats://{}:{}'.format(config['host'], config['port']) servers = [server] opts = {"servers": servers} yield client.connect(**opts) # create and register subscriber(s) inbound_twitter_sub = subscribers.InboundTwitter(client) future = client.subscribe("inboundTwitter", "Twitterqueue", inbound_twitter_sub.handler) log.info("nats subscription started for inboundTwitter") future.result()
def main(): nc = NATS() try: # Setting explicit list of servers in a cluster and # max reconnect retries. servers = [ "nats://127.0.0.1:4222", "nats://127.0.0.1:4223", "nats://127.0.0.1:4224" ] yield nc.connect(max_reconnect_attempts=2, servers=servers) except ErrNoServers: print("No servers available!") return @tornado.gen.coroutine def message_handler(msg): subject = msg.subject reply = msg.reply data = msg.data.decode() for i in range(0, 20): yield nc.publish(reply, "i={i}".format(i=i).encode()) yield nc.subscribe("help.>", cb=message_handler) @tornado.gen.coroutine def request_handler(msg): subject = msg.subject reply = msg.reply data = msg.data.decode() print("Received a message on '{subject} {reply}': {data}".format( subject=subject, reply=reply, data=data)) # Signal the server to stop sending messages after we got 10 already. yield nc.request("help.please", b'help', expected=10, cb=request_handler) # Flush connection to server, returns when all messages have been processed. # It raises a timeout if roundtrip takes longer than 1 second. yield nc.flush() # Drain gracefully closes the connection, allowing all subscribers to # handle any pending messages inflight that the server may have sent. yield nc.drain() # Drain works async in the background. yield tornado.gen.sleep(1)
def main(): nc = NATS() conn_closed = tornado.concurrent.Future() def closed_cb(): conn_closed.set_result(True) # Set pool servers in the cluster and give a name to the client. yield nc.connect("127.0.0.1:4222", closed_cb=closed_cb) @tornado.gen.coroutine def handler(msg): # Can check whether client is in draining state if nc.is_draining: print("[Status ] Draining, will disconnect soon...") print("[Received] {}".format(msg.data)) yield nc.publish(msg.reply, b'I can help') yield nc.subscribe("help", "workers", cb=handler) responses = [] @tornado.gen.coroutine def send_requests(): # Send 100 async requests and wait for all the responses. for i in range(0, 1000): try: response = yield nc.request("help", '[{}] help!'.format(i), timeout=0.1) responses.append(response) except: break loop.current().spawn_callback(send_requests) yield tornado.gen.sleep(1) # Gracefully close the connection and wait for closed callback to be signaled. yield nc.drain() yield conn_closed print("Received {} responses".format(len(responses)))
def test_subscribe(self): nc = Client() options = { "io_loop": self.io_loop } yield nc.connect(**options) self.assertEqual(Client.CONNECTED, nc._status) info_keys = nc._server_info.keys() self.assertTrue(len(info_keys) > 0) inbox = new_inbox() yield nc.subscribe("help.1") yield nc.subscribe("help.2") yield tornado.gen.sleep(0.5) 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(2, connz['subscriptions'])
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(): client = Client() options = {"servers": ["nats://%s:%d" % (NATS_HOST, NATS_PORT)]} yield client.connect(**options) yield client.subscribe(TOPIC, "", handler)
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)