示例#1
0
 async def inner():
     transport = TransactionalEventTransport(
         child_transport=lightbus.RedisEventTransport(
             redis_pool=pool,
             consumer_group_prefix="test_cg",
             consumer_name="test_consumer",
             stream_use=StreamUse.PER_EVENT,
         )
     )
     config = dummy_bus.client.config
     transport_registry = TransportRegistry().load_config(config)
     transport_registry.set_event_transport("default", transport)
     client = lightbus.BusClient(config=config, transport_registry=transport_registry)
     bus = lightbus.path.BusPath(name="", parent=None, client=client)
     return bus
示例#2
0
 def __init_worker___(self):
     self.transport_registry = self.transport_registry or TransportRegistry().load_config(
         self.config
     )
     schema = Schema(
         schema_transport=self.transport_registry.get_schema_transport(),
         max_age_seconds=self.config.bus().schema.ttl,
         human_readable=self.config.bus().schema.human_readable,
     )
     self.schema = WorkerProxy(proxied=schema, worker=self.worker)
def test_setup_transports_opened(mocker):
    rpc_transport = lightbus.DebugRpcTransport()

    # TODO: There has to be a cleaner way of patching a coroutine.
    #       Do a global search for 'dummy_coroutine' if you find it
    async def dummy_coroutine(*args, **kwargs):
        pass

    m = mocker.patch.object(rpc_transport, "open", autospec=True, return_value=dummy_coroutine())

    transport_registry = TransportRegistry().load_config(Config.load_dict({}))
    transport_registry.set_rpc_transport("default", rpc_transport)

    bus = lightbus.creation.create(transport_registry=transport_registry, plugins=[])
    try:
        assert m.call_count == 0

        bus.client.lazy_load_now()
        assert m.call_count == 1
    finally:
        bus.client.close()
示例#4
0
def test_transport_registry_get_specific_api(redis_other_config):
    registry = TransportRegistry().load_config(redis_other_config)
    assert registry.get_rpc_transport("other").__class__ == RedisRpcTransport
    assert registry.get_result_transport(
        "other").__class__ == RedisResultTransport
    assert registry.get_event_transport(
        "other").__class__ == RedisEventTransport
    assert registry.get_schema_transport(
        "other").__class__ == RedisSchemaTransport
示例#5
0
def test_transport_registry_load_config(redis_default_config):
    registry = TransportRegistry().load_config(redis_default_config)
    assert registry.get_rpc_transport("default").__class__ == RedisRpcTransport
    assert registry.get_result_transport(
        "default").__class__ == RedisResultTransport
    assert registry.get_event_transport(
        "default").__class__ == RedisEventTransport
    assert registry.get_schema_transport(
        "default").__class__ == RedisSchemaTransport
示例#6
0
def test_transport_registry_get_does_not_exist_default():
    registry = TransportRegistry()
    with pytest.raises(TransportNotFound):
        assert not registry.get_rpc_transport("default")
    with pytest.raises(TransportNotFound):
        assert not registry.get_result_transport("default")
    with pytest.raises(TransportNotFound):
        assert not registry.get_event_transport("default")
    with pytest.raises(TransportNotFound):
        assert not registry.get_schema_transport()
示例#7
0
    def __init__(self,
                 config: "Config",
                 transport_registry: TransportRegistry = None):

        self.config = config
        self.transport_registry = transport_registry or TransportRegistry(
        ).load_config(config)
        self.schema = Schema(
            schema_transport=self.transport_registry.get_schema_transport(
                "default"),
            max_age_seconds=self.config.bus().schema.ttl,
            human_readable=self.config.bus().schema.human_readable,
        )
        self._listeners = {}
        self._hook_callbacks = defaultdict(list)
        self._exit_code = 0
示例#8
0
def test_transport_registry_get_rpc_transports(redis_default_config):
    registry = TransportRegistry().load_config(redis_default_config)
    debug_transport = DebugRpcTransport()
    redis_transport = RedisRpcTransport()

    registry.set_rpc_transport("redis1", redis_transport)
    registry.set_rpc_transport("redis2", redis_transport)
    registry.set_rpc_transport("debug1", debug_transport)
    registry.set_rpc_transport("debug2", debug_transport)
    transports = registry.get_rpc_transports(
        ["default", "foo", "bar", "redis1", "redis2", "debug1", "debug2"])

    default_redis_transport = registry.get_rpc_transport("default")

    transports = dict(transports)
    assert set(
        transports[default_redis_transport]) == {"default", "foo", "bar"}
    assert set(transports[debug_transport]) == {"debug1", "debug2"}
    assert set(transports[redis_transport]) == {"redis1", "redis2"}
def test_transport_registry_get_event_transports(redis_default_config):
    registry = TransportRegistry().load_config(redis_default_config)
    debug_transport = DebugEventTransport()
    redis_transport = RedisEventTransport(service_name="foo", consumer_name="bar")

    registry.set_event_transport("redis1", redis_transport)
    registry.set_event_transport("redis2", redis_transport)
    registry.set_event_transport("debug1", debug_transport)
    registry.set_event_transport("debug2", debug_transport)
    transports = registry.get_event_transports(
        ["default", "foo", "bar", "redis1", "redis2", "debug1", "debug2"]
    )

    default_redis_transport = registry.get_event_transport("default")

    transports = dict(transports)
    assert set(transports[default_redis_transport]) == {"default", "foo", "bar"}
    assert set(transports[debug_transport]) == {"debug1", "debug2"}
    assert set(transports[redis_transport]) == {"redis1", "redis2"}
示例#10
0
    def __enter__(self):
        rpc = TestRpcTransport()
        result = TestResultTransport()
        event = TestEventTransport()
        schema = TestSchemaTransport()

        new_registry = TransportRegistry()
        new_registry.set_schema_transport(schema)

        self.old_transport_registry = self.bus.client.transport_registry

        for api_name, entry in self.old_transport_registry._registry.items():
            new_registry.set_rpc_transport(api_name, rpc)
            new_registry.set_result_transport(api_name, result)

            if hasattr(entry.event, "child_transport"):
                parent_transport = copy(entry.event)
                parent_transport.child_transport = event
                new_registry.set_event_transport(api_name, parent_transport)
            else:
                new_registry.set_event_transport(api_name, event)

        self.bus.client.transport_registry = new_registry
        return MockResult(rpc, result, event, schema)
示例#11
0
def test_has_schema_transport(redis_no_default_config):
    registry = TransportRegistry().load_config(redis_no_default_config)
    assert registry.has_schema_transport()
    registry.schema_transport = None
    assert not registry.has_schema_transport()
示例#12
0
def test_has_event_transport(redis_no_default_config):
    registry = TransportRegistry().load_config(redis_no_default_config)
    assert registry.has_event_transport("other")
    assert not registry.has_event_transport("foo")
示例#13
0
def test_get_all_transports(redis_default_config):
    registry = TransportRegistry().load_config(redis_default_config)
    registry.set_event_transport("another",
                                 registry.get_event_transport("default"))
    registry.set_event_transport("foo", DebugEventTransport())
    assert len(registry.get_all_transports()) == 4
示例#14
0
async def create_async(
    config: Union[dict, Config] = None,
    *,
    config_file: str = None,
    service_name: str = None,
    process_name: str = None,
    rpc_transport: Optional["RpcTransport"] = None,
    result_transport: Optional["ResultTransport"] = None,
    event_transport: Optional["EventTransport"] = None,
    schema_transport: Optional["SchemaTransport"] = None,
    client_class=BusClient,
    node_class=BusPath,
    plugins=None,
    flask: bool = False,
    **kwargs,
) -> BusPath:
    """
    Create a new bus instance which can be used to access the bus.

    Typically this will be used as follows:

        import lightbus

        bus = await lightbus.create_async()

    This will be a `BusPath` instance. If you wish to access the lower
    level `BusClient` you can do so via `bus.client`.

    See Also:

        `create()` - The synchronous wrapper for this function

    Args:
        config (dict, Config): The config object or dictionary to load
        config_file (str): The path to a config file to load (should end in .json or .yaml)
        service_name (str): The name of this service - will be used when creating event consumer groups
        process_name (str): The unique name of this process - used when retrieving unprocessed events following a crash
        rpc_transport (RpcTransport): The RPC transport instance to use, defaults to Redis
        result_transport (ResultTransport): The result transport instance to use, defaults to Redis
        event_transport (EventTransport): The event transport instance to use, defaults to Redis
        schema_transport (SchemaTransport): The schema transport instance to use, defaults to Redis
        client_class (BusClient): The class from which the bus client will be instantiated
        node_class (BusPath): The class from which the bus path will be instantiated
        plugins (dict): A dictionary of plugins to load, where keys are the plugin name defined in the plugin's entrypoint
        flask (bool): Are we using flask? If so we will make sure we don't start lightbus in the reloader process
        **kwargs (): Any additional instantiation arguments to be passed to `client_class`.

    Returns:

    """
    if flask:
        in_flask_server = sys.argv[0].endswith("flask") and "run" in sys.argv
        if in_flask_server and os.environ.get("WERKZEUG_RUN_MAIN",
                                              "").lower() != "true":
            # Flask has a reloader process that shouldn't start a lightbus client
            return

    from lightbus.config import Config

    # If were are running via the Lightbus CLI then we may have
    # some command line arguments we need to apply.
    from lightbus.commands import COMMAND_PARSED_ARGS

    config_file = COMMAND_PARSED_ARGS.get("config_file", None) or config_file
    service_name = COMMAND_PARSED_ARGS.get("service_name",
                                           None) or service_name
    process_name = COMMAND_PARSED_ARGS.get("process_name",
                                           None) or process_name

    if config is None:
        config = load_config(from_file=config_file,
                             service_name=service_name,
                             process_name=process_name)

    if isinstance(config, Mapping):
        config = Config.load_dict(config or {})

    transport_registry = TransportRegistry().load_config(config)

    # Set transports if specified
    if rpc_transport:
        transport_registry.set_rpc_transport("default", rpc_transport)

    if result_transport:
        transport_registry.set_result_transport("default", result_transport)

    if event_transport:
        transport_registry.set_event_transport("default", event_transport)

    if schema_transport:
        transport_registry.set_schema_transport(schema_transport)

    client = client_class(transport_registry=transport_registry,
                          config=config,
                          **kwargs)
    await client.setup_async(plugins=plugins)

    return node_class(name="", parent=None, client=client)
示例#15
0
def test_transport_registry_get_does_not_exist_default_default_value():
    registry = TransportRegistry()
    assert registry.get_rpc_transport("default", default=None) is None
    assert registry.get_result_transport("default", default=None) is None
    assert registry.get_event_transport("default", default=None) is None
    assert registry.get_schema_transport(default=None) is None
示例#16
0
def create(
    config: Union[dict, RootConfig] = None,
    *,
    config_file: str = None,
    service_name: str = None,
    process_name: str = None,
    features: List[Union[Feature, str]] = ALL_FEATURES,
    client_class: Type[BusClient] = BusClient,
    node_class: Type[BusPath] = BusPath,
    plugins=None,
    flask: bool = False,
    **kwargs,
) -> BusPath:
    """
    Create a new bus instance which can be used to access the bus.

    Typically this will be used as follows:

        import lightbus

        bus = lightbus.create()

    This will be a `BusPath` instance. If you wish to access the lower
    level `BusClient` you can do so via `bus.client`.

    Args:
        config (dict, Config): The config object or dictionary to load
        config_file (str): The path to a config file to load (should end in .json or .yaml)
        service_name (str): The name of this service - will be used when creating event consumer groups
        process_name (str): The unique name of this process - used when retrieving unprocessed events following a crash
        client_class (Type[BusClient]): The class from which the bus client will be instantiated
        node_class (BusPath): The class from which the bus path will be instantiated
        plugins (list): A list of plugin instances to load
        flask (bool): Are we using flask? If so we will make sure we don't start lightbus in the reloader process
        **kwargs (): Any additional instantiation arguments to be passed to `client_class`.

    Returns: BusPath

    """
    if flask:
        in_flask_server = sys.argv[0].endswith("flask") and "run" in sys.argv
        if in_flask_server and os.environ.get("WERKZEUG_RUN_MAIN", "").lower() != "true":
            # Flask has a reloader process that shouldn't start a lightbus client
            return

    # If were are running via the Lightbus CLI then we may have
    # some command line arguments we need to apply.
    # pylint: disable=cyclic-import,import-outside-toplevel
    from lightbus.commands import COMMAND_PARSED_ARGS

    config_file = COMMAND_PARSED_ARGS.get("config_file", None) or config_file
    service_name = COMMAND_PARSED_ARGS.get("service_name", None) or service_name
    process_name = COMMAND_PARSED_ARGS.get("process_name", None) or process_name

    if config is None:
        config = load_config(
            from_file=config_file, service_name=service_name, process_name=process_name
        )

    if isinstance(config, Mapping):
        config = Config.load_dict(config or {})
    elif isinstance(config, RootConfig):
        config = Config(config)

    transport_registry = kwargs.pop("transport_registry", None) or TransportRegistry().load_config(
        config
    )

    client = client_class(
        transport_registry=transport_registry,
        config=config,
        features=features,
        plugins=plugins,
        **kwargs,
    )

    return node_class(name="", parent=None, client=client)
示例#17
0
    def __enter__(self):
        """Start of a context where all the bus' transports have been replaced with mocks"""
        rpc = TestRpcTransport()
        result = TestResultTransport(require_mocking=self.require_mocking)
        event = TestEventTransport(require_mocking=self.require_mocking)
        schema = TestSchemaTransport()

        new_registry = TransportRegistry()
        new_registry.set_schema_transport(schema)

        self.old_transport_registry = self.bus.client.transport_registry

        for api_name, entry in self.old_transport_registry._registry.items():
            new_registry.set_rpc_transport(api_name, rpc)
            new_registry.set_result_transport(api_name, result)

            if hasattr(entry.event, "child_transport"):
                parent_transport = copy(entry.event)
                parent_transport.child_transport = event
                new_registry.set_event_transport(api_name, parent_transport)
            else:
                new_registry.set_event_transport(api_name, event)

        self.bus.client.transport_registry = new_registry
        return MockResult(rpc, result, event, schema)