Пример #1
0
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!')
Пример #2
0
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...")
Пример #3
0
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')
Пример #4
0
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()
Пример #5
0
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))
Пример #6
0
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()
Пример #7
0
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')))
Пример #8
0
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")
Пример #9
0
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()
Пример #10
0
 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
Пример #11
0
    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()
Пример #12
0
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()
Пример #13
0
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()
Пример #14
0
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
Пример #15
0
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)
Пример #16
0
 async def start_nats(self):
     self.nats_client = NatsClient()
     await self.nats_client.connect(io_loop=self.loop, servers=[NATS_URL])
Пример #17
0
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()