async def nats_consume(loop): nc = NatsClient() await nc.connect("localhost:4222", loop=loop) if nc.is_connected: await nc.subscribe('django_out', cb=generator_task) else: raise Exception('Cant reach broker!')
async def main(): # Declare the protocol stack used for serialization. # Protocol stacks must match between publishers and subscribers. prot_factory = FProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()) # Open a NATS connection to receive requests nats_client = NatsClient() options = {"verbose": True, "servers": ["nats://127.0.0.1:4222"]} await nats_client.connect(**options) # Create a pub sub scope using the configured transport and protocol transport_factory = FNatsSubscriberTransportFactory(nats_client) provider = FScopeProvider(None, transport_factory, prot_factory) subscriber = AlbumWinnersSubscriber(provider) def event_handler(ctx, req): root.info("You won! {}".format(req.ASIN)) def start_contest_handler(ctx, albums): root.info("Contest started, available albums: {}".format(albums)) await subscriber.subscribe_Winner(event_handler) await subscriber.subscribe_ContestStart(start_contest_handler) root.info("Subscriber starting...")
async def main(): nc = NatsClient() sc = StanClient() print_msg('Client initiated') try: await nc.connect(servers=['nats://nats:4223'], io_loop=asyncio.get_running_loop()) await sc.connect('test-cluster', f'simple_service_client_{ObjectId()}', nats=nc) print_msg('Connected to NATS') except ErrNoServers as e: print(e) return async def on_created(msg): subject = msg.sub data = msg.data.decode() body = json.loads(data) print( f"{get_current_time()}[PID: {os.getpid()}] Received a message on '{subject} ': {data}" ) async def new_task(event_data: dict): res = await asyncio.get_running_loop().run_in_executor( executor, simple_task, event_data) print('>>>>>>>>>>>>>>>>>>>>>>>>>>>', res) await sc.publish('task:simple:finished', payload=b'{"test": "test"}') print('<<<<<<<<<<<<<<<<<<<<<<<<<<<') asyncio.create_task(new_task(body)) await sc.subscribe("simple:created", cb=on_created, queue="simple.queue") print_msg('Subscribed to the simple:created channel')
async def main(): # Declare the protocol stack used for serialization. # Protocol stacks must match between clients and servers. prot_factory = FProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()) # Open a NATS connection to send requests nats_client = NatsClient() options = {"verbose": True, "servers": ["nats://127.0.0.1:4222"]} await nats_client.connect(**options) # Create a nats transport using the connected client # The transport sends data on the music-service NATS topic nats_transport = FNatsTransport(nats_client, "music-service") try: await nats_transport.open() except TTransportException as ex: root.error(ex) return # Using the configured transport and protocol, create a client # to talk to the music store service. store_client = FStoreClient(FServiceProvider(nats_transport, prot_factory), middleware=logging_middleware) album = await store_client.buyAlbum(FContext(), str(uuid.uuid4()), "ACT-12345") root.info("Bought an album %s\n", album.tracks[0].title) await store_client.enterAlbumGiveaway(FContext(), "*****@*****.**", "Kevin") # Close transport and nats client await nats_transport.close() await nats_client.close()
async def main(loop): nc = NatsClient() await nc.connect(io_loop=loop, servers=['nats://127.0.0.1:4222'], verbose=True) client_1_0 = RemoteService(name='test', version='1.0', nc=nc) client_1_1 = RemoteService(name='test', version='1.1', nc=nc) client_2_0 = RemoteService(name='test', version='2.0', nc=nc) print(await client_1_0.ping()) print(await client_1_1.ping()) print(await client_2_0.ping()) print(await client_2_0.hello('world')) print(await client_2_0.add(12, 54))
async def run_loop(loop, nats_config: nats_constructor.Config, dao: dao_module.Dao): topic = "gpx_files.gpx_file" nats_client = NatsClient() logger.info("connecting", extra=logging_utils.wrap_props({"url": nats_config.url})) await nats_client.connect(nats_config.url, loop=loop) logger.info("subscribing...") await nats_client.subscribe(topic, cb=message_call_back) logger.info("draining") await nats_client.drain()
async def run(async_loop): nc = NatsClient() sc = StanClient() try: await nc.connect(servers=['nats://localhost:4223'], io_loop=async_loop) await sc.connect('test-cluster', f'simple_service_client_{ObjectId()}', nats=nc) except ErrNoServers as e: print(e) return for i in range(10): message = json.dumps({"simple": f"simple_{i}"}) await sc.publish('simple:created', bytes(message.encode('utf-8')))
async def main(loop): await asyncio.sleep(1) nc = NatsClient() await nc.connect(io_loop=loop, servers=[NATS_URI], verbose=True) remote = RemoteService(name='notifications_producer', version='1.0', nc=nc) logging.debug("main: calling remote procedure") try: print(await remote.do_stuff_and_notify()) print(await remote.do_more_stuff_and_notify()) except MiteDRPCError as err: logging.error(err) logging.debug("main: exiting")
async def main(): parser = argparse.ArgumentParser(description="Run a python asyncio client") parser.add_argument('--port', dest='port', default='9090') parser.add_argument('--protocol', dest='protocol_type', default="binary", choices="binary, compact, json") parser.add_argument('--transport', dest='transport_type', default=NATS_NAME, choices="nats, http") args = parser.parse_args() protocol_factory = get_protocol_factory(args.protocol_type) nats_client = NatsClient() await nats_client.connect(**get_nats_options()) transport = None if args.transport_type == NATS_NAME: transport = FNatsTransport(nats_client, "frugal.foo.bar.rpc.{}".format(args.port)) await transport.open() elif args.transport_type == HTTP_NAME: # Set request and response capacity to 1mb max_size = 1048576 transport = FHttpTransport( "http://localhost:{port}".format(port=args.port), request_capacity=max_size, response_capacity=max_size) else: print( "Unknown transport type: {type}".format(type=args.transport_type)) sys.exit(1) client = FrugalTestClient(FServiceProvider(transport, protocol_factory), client_middleware) ctx = FContext("test") await test_rpc(client, ctx, args.transport_type) if transport == NATS_NAME: await test_pub_sub(nats_client, protocol_factory, args.port) await nats_client.close()
async def _connect(self): result = False if self.nats_client is None: self.nats_client = NatsClient() try: await self.nats_client.connect( **self._params.dict(), io_loop=asyncio.get_running_loop(), disconnected_cb=self._disconnected_cb, reconnected_cb=self._reconnected_cb, error_cb=self._error_cb, closed_cb=self._closed_cb) result = self.nats_client.is_connected except Exception as exception: self.logger.exception(exception) self.nats_client = None return result
def main(self, loop): """Connect to remote host(s) Raises: NoServersError """ # explicitly set the asyncio event loop so it can't get confused .. asyncio.set_event_loop(loop) self._conn = NatsClient() try: yield from self._conn.connect(io_loop=loop, **self.opts) except nats_errors.ErrNoServers as e: # Could not connect to any server in the cluster. raise errors.NoServersError(e) while self._running: if self._outgoing.empty(): # No one wants to send a message continue if not self._conn.is_connected: # give nats more time to (re)connect continue reply_queue, key, data = self._outgoing.get_nowait( ) # pull request from queue if reply_queue is None: # we're passed None only when we're supposed to exit. See stop() break try: result = yield from self._conn.request( key, bytes(data, encoding="utf8")) reply_queue.put_nowait(result.data.decode()) except nats_errors.ErrConnectionClosed as e: reply_queue.put_nowait(errors.ConnectionClosedError(e)) except (nats_errors.ErrTimeout, queue.Empty) as e: reply_queue.put_nowait(errors.RequestTimeoutError(e)) except Exception as e: # pass all errors up to the caller reply_queue.put_nowait(e) yield from self._conn.close()
async def main(): parser = argparse.ArgumentParser(description="Run a python asyncio client") parser.add_argument('--port', dest='port', default='9090') parser.add_argument('--protocol', dest='protocol_type', default="binary", choices="binary, compact, json") parser.add_argument('--transport', dest='transport_type', default="stateless", choices="stateless, stateless-stateful, http") args = parser.parse_args() protocol_factory = get_protocol_factory(args.protocol_type) nats_client = NatsClient() await nats_client.connect(**get_nats_options()) transport = None if args.transport_type in ["stateless", "stateless-stateful"]: transport = FNatsTransport(nats_client, "frugal.foo.bar.rpc.{}".format(args.port)) await transport.open() elif args.transport_type == "http": transport = FHttpTransport( "http://localhost:{port}".format(port=args.port)) else: print( "Unknown transport type: {type}".format(type=args.transport_type)) sys.exit(1) client = FrugalTestClient(FServiceProvider(transport, protocol_factory), client_middleware) ctx = FContext("test") await test_rpc(client, ctx) await test_pub_sub(nats_client, protocol_factory, args.port) await nats_client.close()
async def main(): # Declare the protocol stack used for serialization. # Protocol stacks must match between publishers and subscribers. prot_factory = FProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()) # Open a NATS connection to receive requests nats_client = NatsClient() options = { "verbose": True, "servers": ["nats://127.0.0.1:4222"] } await nats_client.connect(**options) # Create a pub sub scope using the configured transport and protocol transport_factory = FNatsPublisherTransportFactory(nats_client) provider = FScopeProvider(transport_factory, None, prot_factory) # Create a publisher publisher = AlbumWinnersPublisher(provider) await publisher.open() # Publish an album win event album = Album() album.ASIN = str(uuid.uuid4()) album.duration = 12000 album.tracks = [Track(title="Comme des enfants", artist="Coeur de pirate", publisher="Grosse Boîte", composer="Béatrice Martin", duration=169, pro=PerfRightsOrg.ASCAP)] await publisher.publish_Winner(FContext(), album) await publisher.publish_ContestStart(FContext(), [album, album]) # Close publisher and nats client await publisher.close() await nats_client.close()
async def create_nats_client(servers: List[str]) -> Optional[NatsClient]: """ Create a NATS client for any NATS server or NATS cluster. :param servers: List of one or more NATS servers. If multiple servers are provided, they should be in the same NATS cluster. :return: a connected NATS client instance """ settings = get_settings() ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH) ssl_ctx.load_verify_locations(settings.nats_rootCA_file) nats_client = NatsClient() await nats_client.connect( servers=servers, loop=get_running_loop(), tls=ssl_ctx, allow_reconnect=settings.nats_allow_reconnect, max_reconnect_attempts=settings.nats_max_reconnect_attempts) logger.debug(f'Created NATS client for servers = {servers}') return nats_client
class NatsServiceBase(ArgumentParserMixin, MsgPackMixin, LoggerMixin, AsyncServiceMixin): """ Базовый класс для работы с NATS Добавляется параметр командной строки --nats-servers. Оборачиваются функции publish и subscribe для NATS, при это для подписки автоматически может формироваться имя обработчика. Example: :: svc = NetcatService() svc.async_run_until_complete() """ NATS_SERVERS = [ 'nats://localhost:4333', ] """Перечень обработчиков для тем сообщений""" _nats_subject_handler = {} """Параметры соединения клиента, включая обработчики""" _nats_options = {} """Собственно клиент NATS""" nats_client = NatsClient() def _nats_get_connection_string(self): return self.argument_parser_options.nats_servers async def _nats_error_handler(self, e): """Обработчик ошибок NATS по-умолчанию""" self._logger.error(f'{type(e).__name__} {e}') async def _nats_closed_handler(self): """Обработчик закрытия NATS по-умолчанию""" self._logger.debug("Connection to NATS is closed.") async def _nats_reconnected_handler(self): """Обработчик повторного соединения к NATS по-умолчанию""" self._logger.debug( f"Connected to NATS at {self.nats_client.connected_url.netloc}...") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) """Добавить аргумент командной строки --nats-servers nats://<host>:<port>""" self.argument_parser_add('--nats-servers', default=self.NATS_SERVERS, action='append') options = { 'servers': self._nats_get_connection_string(), 'error_cb': self._nats_error_handler, 'closed_cb': self._nats_closed_handler, 'reconnected_cb': self._nats_reconnected_handler } self._nats_options = options def _nats_get_handler(self, subject): """ Получение обработчика для темы сообщения - Если тема есть в специальном словаре _nats_subject_handler, то брать оттуда. - Если там указан класс, который инициализируется с параметрами nats_client и async_loop, обработчик - метод message_handler - Если там указана функция, то брать её - Если нет, то заменить все . на _, вместо * писать __star__, вместо > писать __next__, впереди добавить _nats_handler_ """ handler = None if subject in self._nats_subject_handler: if issubclass(self._nats_subject_handler[subject], NatsSubscriberBase): obj = self._nats_subject_handler[subject]( nats_client=self.nats_client, async_loop=self.async_loop) handler = obj.message_handler self._nats_subject_handler[subject] = handler elif inspect.isfunction( self._nats_subject_handler[subject]) or inspect.ismethod( self._nats_subject_handler[subject]): handler = self._nats_subject_handler[subject] else: raise TypeError( f'unknown "{subject}" handler (may be a function or a NatsScribeBase subclass' ) else: handler_name = '_nats_handler_' + subject.replace( '.', '_').replace('*', '__star__').replace('>', '__next__') handler = getattr(self, handler_name) return handler async def nats_subscribe(self, subject, queue='', handler=None): """ Добавление подписки на сообщения NATS :param subject: тема сообщения, например 'my.task' :param queue: название очереди сообщений для горизонтального масштабирования :param handler: обработчик (callback функция) :return: **ssid** подписки """ if handler is None: handler = self._nats_get_handler(subject) await self.nats_client.subscribe(subject, queue, cb=handler) async def _nats_subscribe(self, *args, **kwargs): """Обёртка для подписки (получения сообщений) NATS""" return await self.nats_client.subscribe(*args, **kwargs) async def _nats_publish(self, *args, **kwargs): """Обёртка для публикации (отправки сообщения) NATS""" return await self.nats_client.publish(*args, **kwargs) async def nats_publish(self, *args, **kwargs): """Публикация (отправка сообщений) NATS""" return await self._nats_publish(*args, **kwargs) async def run_async(self): """Точка входа в асинхронный сервис""" await super().run_async() self._nats_options['servers'] = self._nats_get_connection_string() await self.nats_client.connect(**self._nats_options)
async def start_nats(self): self.nats_client = NatsClient() await self.nats_client.connect(io_loop=self.loop, servers=[NATS_URL])
async def main(): parser = argparse.ArgumentParser( description="Run an asyncio python server") parser.add_argument('--port', dest='port', default='9090') parser.add_argument('--protocol', dest='protocol_type', default="binary", choices="binary, compact, json") parser.add_argument('--transport', dest="transport_type", default=NATS_NAME, choices="nats, http") args = parser.parse_args() protocol_factory = get_protocol_factory(args.protocol_type) nats_client = NatsClient() await nats_client.connect(**get_nats_options()) port = args.port handler = FrugalTestHandler() subject = "frugal.*.*.rpc.{}".format(args.port) processor = Processor(handler) # Setup subscriber, send response upon receipt pub_transport_factory = FNatsPublisherTransportFactory(nats_client) sub_transport_factory = FNatsSubscriberTransportFactory(nats_client) provider = FScopeProvider(pub_transport_factory, sub_transport_factory, protocol_factory) publisher = EventsPublisher(provider) await publisher.open() async def response_handler(context, event): preamble = context.get_request_header(PREAMBLE_HEADER) if preamble is None or preamble == "": logging.error("Client did not provide preamble header") return ramble = context.get_request_header(RAMBLE_HEADER) if ramble is None or ramble == "": logging.error("Client did not provide ramble header") return response_event = Event(Message="Sending Response") response_context = FContext("Call") await publisher.publish_EventCreated(response_context, preamble, ramble, "response", "{}".format(port), response_event) subscriber = EventsSubscriber(provider) await subscriber.subscribe_EventCreated("*", "*", "call", "{}".format(args.port), response_handler) if args.transport_type == NATS_NAME: server = FNatsServer(nats_client, [subject], processor, protocol_factory) # start healthcheck so the test runner knows the server is running threading.Thread(target=healthcheck, args=(port, )).start() print("Starting {} server...".format(args.transport_type)) await server.serve() elif args.transport_type == HTTP_NAME: print('starting http server') handler = new_http_handler(processor, protocol_factory) app = web.Application(loop=asyncio.get_event_loop()) app.router.add_route("*", "/", handler) srv = await asyncio.get_event_loop().create_server( app.make_handler(), '0.0.0.0', port) else: logging.error("Unknown transport type: %s", args.transport_type) sys.exit(1)
async def send_message(nats_url, message, loop): client = NatsClient() await client.connect(io_loop=loop, servers=[nats_url]) await client.publish("clickevent.stagingdata", message) logging.debug(f"Sent the message") await client.close()