dbt click包执行上下文manifest 处理简单说明

dbt 的cli 执行是基于了click 者pip 包,同时为了方便执行(比如依赖的参数),dbt 核心比较重要的是manifest
这个参数是通过context 传递的

run 参考task 处理

  • 参考代码
    core dbt/cli/main.py
@cli.command("run")
@click.pass_context
@global_flags
@p.exclude
@p.full_refresh
@p.profile
@p.profiles_dir
@p.project_dir
@p.empty
@p.select
@p.selector
@p.target
@p.target_path
@p.threads
@p.vars
@requires.postflight
@requires.preflight
@requires.profile
@requires.project
@requires.runtime_config
@requires.manifest
def run(ctx, **kwargs):
    """Compile SQL and execute against the current target database."""
    task = RunTask(
        ctx.obj["flags"],
        ctx.obj["runtime_config"],
        ctx.obj["manifest"],
    )
  • 简单说明
    cli.command 以及 click.pass_context 就是标准的click 配置p 是配置参数相关的,requires 是必须项,db基于了装饰器进行处理
    @requires.manifest 是一个比较重要的东西dbt 好多命令都是需要此参数的, ctx.obj["manifest"] 此数据是通过装饰器处理的

manifest 参考处理

  • core requires.py
def manifest(*args0, write=True, write_perf_info=False):
    """A decorator used by click command functions for generating a manifest
    given a profile, project, and runtime config. This also registers the adapter
    from the runtime config and conditionally writes the manifest to disk.
    """
 
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            ctx = args[0]
            assert isinstance(ctx, Context)
 
            req_strs = ["profile", "project", "runtime_config"]
            reqs = [ctx.obj.get(dep) for dep in req_strs]
 
            if None in reqs:
                raise DbtProjectError("profile, project, and runtime_config required for manifest")
 
            runtime_config = ctx.obj["runtime_config"]
 
            # a manifest has already been set on the context, so don't overwrite it
            if ctx.obj.get("manifest") is None:
               # 如果数据为空,会进行解析生成(会结合runtime 配置信息)
                ctx.obj["manifest"] = parse_manifest(
                    runtime_config, write_perf_info, write, ctx.obj["flags"].write_json
                )
            else:
               # 已经包含了需要的信息,会进行adapter 的注册,以及macro 的解析处理
                register_adapter(runtime_config, get_mp_context())
                adapter = get_adapter(runtime_config)
                adapter.set_macro_context_generator(generate_runtime_macro_context)
                adapter.set_macro_resolver(ctx.obj["manifest"])
                query_header_context = generate_query_header_context(
                    adapter.config, ctx.obj["manifest"]
                )
                adapter.connections.set_query_header(query_header_context)
            return func(*args, **kwargs)
 
        return update_wrapper(wrapper, func)
 
    # if there are no args, the decorator was used without params @decorator
    # otherwise, the decorator was called with params @decorator(arg)
    if len(args0) == 0:
        return outer_wrapper
    return outer_wrapper(args0[0])

parse_manifest 处理

def parse_manifest(runtime_config, write_perf_info, write, write_json):
   # 进行adapter 注册
    register_adapter(runtime_config, get_mp_context())
   # 使用注册的adapter 进行 macro context 处理
    adapter = get_adapter(runtime_config)
    adapter.set_macro_context_generator(generate_runtime_macro_context)
    # ManifestLoader 加载完整的manifest
    manifest = ManifestLoader.get_full_manifest(
        runtime_config,
        write_perf_info=write_perf_info,
    )
   # 写入manifest 到target 文件夹下
    if write and write_json:
        write_manifest(manifest, runtime_config.project_target_path)
        pm = plugins.get_plugin_manager(runtime_config.project_name)
        plugin_artifacts = pm.get_manifest_artifacts(manifest)
        for path, plugin_artifact in plugin_artifacts.items():
            plugin_artifact.write(path)
    return manifest
    )

说明

以上只是简单的说明manifest 参数是如何处理以及其他cli 参数的使用,详细解析里边比较复杂,后续会通过源码分析下实际的处理

参考资料

https://github.com/dbt-labs/dbt-core/blob/main/core/dbt/cli/requires.py
https://github.com/dbt-labs/dbt-core/blob/main/core/dbt/cli/main.py#L558
https://github.com/dbt-labs/dbt-core

posted on 2024-04-03 00:47  荣锋亮  阅读(9)  评论(0编辑  收藏  举报

导航