예제 #1
0
    def test_backfill(self, storage):
        origin = self.fake_partition_set_origin("fake_partition_set")
        backfills = storage.get_backfills()
        assert len(backfills) == 0

        one = PartitionBackfill(
            "one",
            origin,
            BulkActionStatus.REQUESTED,
            ["a", "b", "c"],
            False,
            None,
            None,
            pendulum.now().timestamp(),
        )
        storage.add_backfill(one)
        assert len(storage.get_backfills()) == 1
        assert len(
            storage.get_backfills(status=BulkActionStatus.REQUESTED)) == 1
        backfill = storage.get_backfill(one.backfill_id)
        assert backfill == one

        storage.update_backfill(
            one.with_status(status=BulkActionStatus.COMPLETED))
        assert len(storage.get_backfills()) == 1
        assert len(
            storage.get_backfills(status=BulkActionStatus.REQUESTED)) == 0
def test_simple(external_repo_context, capfd):
    with instance_for_context(external_repo_context) as (
            instance,
            _grpc_server_registry,
            external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set(
            "simple_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        launch_process = multiprocessing.Process(
            target=_test_backfill_in_subprocess,
            args=[instance.get_ref(), None],
        )
        launch_process.start()
        launch_process.join(timeout=60)
        backfill = instance.get_backfill("simple")
        assert backfill.status == BulkActionStatus.COMPLETED
        captured = capfd.readouterr()
        assert (
            captured.out.replace("\r\n", "\n") ==
            """2021-02-16 18:00:00 - BackfillDaemon - INFO - Starting backfill for simple
2021-02-16 18:00:00 - BackfillDaemon - INFO - Backfill completed for simple for 3 partitions
""")
예제 #3
0
def test_simple(capfd):
    with instance_for_context(default_repo) as (
            instance,
            _grpc_server_registry,
            external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set(
            "simple_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        launch_process = spawn_ctx.Process(
            target=_test_backfill_in_subprocess,
            args=[instance.get_ref(), None],
        )
        launch_process.start()
        launch_process.join(timeout=60)
        backfill = instance.get_backfill("simple")
        assert backfill.status == BulkActionStatus.COMPLETED
        assert (
            get_logger_output_from_capfd(capfd,
                                         "dagster.daemon.BackfillDaemon") ==
            """2021-02-16 18:00:00 -0600 - dagster.daemon.BackfillDaemon - INFO - Starting backfill for simple
2021-02-16 18:00:00 -0600 - dagster.daemon.BackfillDaemon - INFO - Backfill completed for simple for 3 partitions"""
        )
예제 #4
0
def test_large_backfill(external_repo_context):
    with instance_for_context(external_repo_context) as (
            instance,
            grpc_server_registry,
            external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set(
            "large_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        assert instance.get_runs_count() == 0

        list(
            execute_backfill_iteration(
                instance, grpc_server_registry,
                get_default_daemon_logger("BackfillDaemon")))

        assert instance.get_runs_count() == 3
예제 #5
0
def test_unloadable_backfill(external_repo_context):
    with instance_for_context(external_repo_context) as (
            instance,
            workspace,
            _external_repo,
    ):
        unloadable_origin = _unloadable_partition_set_origin()
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=unloadable_origin,
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        assert instance.get_runs_count() == 0

        list(
            execute_backfill_iteration(
                instance, workspace,
                get_default_daemon_logger("BackfillDaemon")))

        assert instance.get_runs_count() == 0
        backfill = instance.get_backfill("simple")
        assert backfill.status == BulkActionStatus.FAILED
        assert isinstance(backfill.error, SerializableErrorInfo)
예제 #6
0
파일: backfill.py 프로젝트: zuik/dagster
def create_and_launch_partition_backfill(graphene_info, backfill_params):
    from ...schema.backfill import GrapheneLaunchBackfillSuccess
    from ...schema.errors import GraphenePartitionSetNotFoundError

    partition_set_selector = backfill_params.get("selector")
    partition_set_name = partition_set_selector.get("partitionSetName")
    repository_selector = RepositorySelector.from_graphql_input(
        partition_set_selector.get("repositorySelector"))
    location = graphene_info.context.get_repository_location(
        repository_selector.location_name)
    repository = location.get_repository(repository_selector.repository_name)
    matches = [
        partition_set
        for partition_set in repository.get_external_partition_sets()
        if partition_set.name == partition_set_selector.get("partitionSetName")
    ]
    if not matches:
        return GraphenePartitionSetNotFoundError(partition_set_name)

    check.invariant(
        len(matches) == 1,
        "Partition set names must be unique: found {num} matches for {partition_set_name}"
        .format(num=len(matches), partition_set_name=partition_set_name),
    )

    external_partition_set = next(iter(matches))

    partition_names = backfill_params.get("partitionNames")

    backfill_id = make_new_backfill_id()
    backfill = PartitionBackfill(
        backfill_id=backfill_id,
        partition_set_origin=external_partition_set.get_external_origin(),
        status=BulkActionStatus.REQUESTED,
        partition_names=partition_names,
        from_failure=bool(backfill_params.get("fromFailure")),
        reexecution_steps=backfill_params.get("reexecutionSteps"),
        tags={t["key"]: t["value"]
              for t in backfill_params.get("tags", [])},
        backfill_timestamp=pendulum.now("UTC").timestamp(),
    )

    if backfill_params.get("forceSynchronousSubmission"):
        # should only be used in a test situation
        to_submit = [name for name in partition_names]
        submitted_run_ids = []

        while to_submit:
            chunk = to_submit[:BACKFILL_CHUNK_SIZE]
            to_submit = to_submit[BACKFILL_CHUNK_SIZE:]
            submitted_run_ids.extend(run_id for run_id in submit_backfill_runs(
                graphene_info.context.instance,
                location,
                backfill,
                partition_names=chunk) if run_id != None)
        return GrapheneLaunchBackfillSuccess(
            backfill_id=backfill_id, launched_run_ids=submitted_run_ids)

    graphene_info.context.instance.add_backfill(backfill)
    return GrapheneLaunchBackfillSuccess(backfill_id=backfill_id)
예제 #7
0
def test_canceled_backfill():
    with instance_for_context(default_repo) as (
            instance,
            workspace,
            external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set(
            "simple_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        assert instance.get_runs_count() == 0

        iterator = execute_backfill_iteration(
            instance, workspace, get_default_daemon_logger("BackfillDaemon"))
        next(iterator)
        assert instance.get_runs_count() == 1
        backfill = instance.get_backfills()[0]
        assert backfill.status == BulkActionStatus.REQUESTED
        instance.update_backfill(
            backfill.with_status(BulkActionStatus.CANCELED))
        list(iterator)
        backfill = instance.get_backfill(backfill.backfill_id)
        assert backfill.status == BulkActionStatus.CANCELED
        assert instance.get_runs_count() == 1
예제 #8
0
def test_simple_backfill(external_repo_context):
    with instance_for_context(external_repo_context) as (instance,
                                                         external_repo):
        external_partition_set = external_repo.get_external_partition_set(
            "simple_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        assert instance.get_runs_count() == 0

        list(
            execute_backfill_iteration(
                instance, get_default_daemon_logger("BackfillDaemon")))

        assert instance.get_runs_count() == 3
        runs = instance.get_runs()
        three, two, one = runs
        assert one.tags[BACKFILL_ID_TAG] == "simple"
        assert one.tags[PARTITION_NAME_TAG] == "one"
        assert two.tags[BACKFILL_ID_TAG] == "simple"
        assert two.tags[PARTITION_NAME_TAG] == "two"
        assert three.tags[BACKFILL_ID_TAG] == "simple"
        assert three.tags[PARTITION_NAME_TAG] == "three"
예제 #9
0
def create_and_launch_partition_backfill(graphene_info, backfill_params):
    from ...schema.backfill import GraphenePartitionBackfillSuccess
    from ...schema.errors import GraphenePartitionSetNotFoundError

    partition_set_selector = backfill_params.get("selector")
    partition_set_name = partition_set_selector.get("partitionSetName")
    repository_selector = RepositorySelector.from_graphql_input(
        partition_set_selector.get("repositorySelector"))
    location = graphene_info.context.get_repository_location(
        repository_selector.location_name)
    repository = location.get_repository(repository_selector.repository_name)
    matches = [
        partition_set
        for partition_set in repository.get_external_partition_sets()
        if partition_set.name == partition_set_selector.get("partitionSetName")
    ]
    if not matches:
        return GraphenePartitionSetNotFoundError(partition_set_name)

    check.invariant(
        len(matches) == 1,
        "Partition set names must be unique: found {num} matches for {partition_set_name}"
        .format(num=len(matches), partition_set_name=partition_set_name),
    )

    external_partition_set = next(iter(matches))

    partition_names = backfill_params.get("partitionNames")

    backfill_id = make_new_backfill_id()
    backfill = PartitionBackfill(
        backfill_id=backfill_id,
        partition_set_origin=external_partition_set.get_external_origin(),
        status=BulkActionStatus.REQUESTED,
        partition_names=partition_names,
        from_failure=bool(backfill_params.get("fromFailure")),
        reexecution_steps=backfill_params.get("reexecutionSteps"),
        tags={t["key"]: t["value"]
              for t in backfill_params.get("tags", [])},
        backfill_timestamp=pendulum.now("UTC").timestamp(),
    )

    backfill_settings = graphene_info.context.instance.get_settings(
        "backfill") or {}
    daemonEnabled = backfill_settings.get("daemon_enabled")
    if daemonEnabled and not graphene_info.context.instance.has_bulk_actions_table(
    ):
        check.failed(
            "A schema migration is required before daemon-based backfills can be supported. "
            "Try running `dagster instance migrate` to migrate your instance and try again."
        )
    elif daemonEnabled:
        graphene_info.context.instance.add_backfill(backfill)
        return GraphenePartitionBackfillSuccess(backfill_id=backfill_id)
    else:
        submitted_run_ids = submit_backfill_runs(
            graphene_info.context.instance, location, backfill)
        return GraphenePartitionBackfillSuccess(
            backfill_id=backfill_id, launched_run_ids=submitted_run_ids)
예제 #10
0
def test_crash_after_submit(external_repo_context, crash_signal, capfd):
    with instance_for_context(external_repo_context) as (instance,
                                                         external_repo):
        external_partition_set = external_repo.get_external_partition_set(
            "simple_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        launch_process = multiprocessing.Process(
            target=_test_backfill_in_subprocess,
            args=[instance.get_ref(), {
                "AFTER_SUBMIT": crash_signal
            }],
        )
        launch_process.start()
        launch_process.join(timeout=60)
        assert launch_process.exitcode != 0
        captured = capfd.readouterr()
        assert (
            captured.out.replace("\r\n", "\n") ==
            """2021-02-16 18:00:00 - BackfillDaemon - INFO - Starting backfill for simple
""")

        backfill = instance.get_backfill("simple")
        assert backfill.status == BulkActionStatus.REQUESTED
        assert instance.get_runs_count() == 3

        # resume backfill
        launch_process = multiprocessing.Process(
            target=_test_backfill_in_subprocess,
            args=[instance.get_ref(), None],
        )
        launch_process.start()
        launch_process.join(timeout=60)
        captured = capfd.readouterr()
        assert (
            captured.out.replace("\r\n", "\n") ==
            """2021-02-16 18:00:00 - BackfillDaemon - INFO - Starting backfill for simple
2021-02-16 18:00:00 - BackfillDaemon - INFO - Found 3 existing runs for backfill simple, skipping
2021-02-16 18:00:00 - BackfillDaemon - INFO - Backfill completed for simple for 3 partitions
""")

        backfill = instance.get_backfill("simple")
        assert backfill.status == BulkActionStatus.COMPLETED
        assert instance.get_runs_count() == 3
예제 #11
0
def test_before_submit(external_repo_context, crash_signal, capfd):
    with instance_for_context(external_repo_context) as (
        instance,
        _grpc_server_registry,
        external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set("simple_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="simple",
                partition_set_origin=external_partition_set.get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            )
        )
        launch_process = multiprocessing.Process(
            target=_test_backfill_in_subprocess,
            args=[instance.get_ref(), {"BEFORE_SUBMIT": crash_signal}],
        )
        launch_process.start()
        launch_process.join(timeout=60)
        assert launch_process.exitcode != 0
        assert (
            get_logger_output_from_capfd(capfd, "dagster.daemon.BackfillDaemon")
            == """2021-02-16 18:00:00 -0600 - dagster.daemon.BackfillDaemon - INFO - Starting backfill for simple"""
        )

        backfill = instance.get_backfill("simple")
        assert backfill.status == BulkActionStatus.REQUESTED
        assert instance.get_runs_count() == 0

        # resume backfill
        launch_process = multiprocessing.Process(
            target=_test_backfill_in_subprocess,
            args=[instance.get_ref(), None],
        )
        launch_process.start()
        launch_process.join(timeout=60)
        assert (
            get_logger_output_from_capfd(capfd, "dagster.daemon.BackfillDaemon")
            == """2021-02-16 18:00:00 -0600 - dagster.daemon.BackfillDaemon - INFO - Starting backfill for simple
2021-02-16 18:00:00 -0600 - dagster.daemon.BackfillDaemon - INFO - Backfill completed for simple for 3 partitions"""
        )

        backfill = instance.get_backfill("simple")
        assert backfill.status == BulkActionStatus.COMPLETED
        assert instance.get_runs_count() == 3
예제 #12
0
def test_backfill_from_failure_for_subselection():
    with instance_for_context(default_repo) as (
        instance,
        workspace,
        external_repo,
    ):
        partition = parallel_failure_partition_set.get_partition("one")
        run_config = parallel_failure_partition_set.run_config_for_partition(partition)
        tags = parallel_failure_partition_set.tags_for_partition(partition)
        external_partition_set = external_repo.get_external_partition_set(
            "parallel_failure_partition_set"
        )

        execute_pipeline(
            parallel_failure_pipeline,
            run_config=run_config,
            tags=tags,
            instance=instance,
            solid_selection=["fail_three", "success_four"],
            raise_on_error=False,
        )

        assert instance.get_runs_count() == 1
        wait_for_all_runs_to_finish(instance)
        run = instance.get_runs()[0]
        assert run.status == PipelineRunStatus.FAILURE

        instance.add_backfill(
            PartitionBackfill(
                backfill_id="fromfailure",
                partition_set_origin=external_partition_set.get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one"],
                from_failure=True,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            )
        )

        list(
            execute_backfill_iteration(
                instance, workspace, get_default_daemon_logger("BackfillDaemon")
            )
        )
        assert instance.get_runs_count() == 2
        run = instance.get_runs(limit=1)[0]
        assert run.solids_to_execute
        assert run.solid_selection
        assert len(run.solids_to_execute) == 2
        assert len(run.solid_selection) == 2
예제 #13
0
def test_backfill_from_partitioned_job(external_repo_context):
    partition_name_list = [
        partition.name
        for partition in my_config.partitions_def.get_partitions()
    ]
    with instance_for_context(external_repo_context) as (
            instance,
            workspace,
            external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set(
            "comp_always_succeed_default_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="partition_schedule_from_job",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=partition_name_list[:3],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        assert instance.get_runs_count() == 0

        list(
            execute_backfill_iteration(
                instance, workspace,
                get_default_daemon_logger("BackfillDaemon")))

        assert instance.get_runs_count() == 3
        runs = reversed(instance.get_runs())
        for idx, run in enumerate(runs):
            assert run.tags[BACKFILL_ID_TAG] == "partition_schedule_from_job"
            assert run.tags[PARTITION_NAME_TAG] == partition_name_list[idx]
            assert run.tags[
                PARTITION_SET_TAG] == "comp_always_succeed_default_partition_set"
예제 #14
0
def _execute_backfill_command_at_location(cli_args, print_fn, instance, workspace, repo_location):
    external_repo = get_external_repository_from_repo_location(
        repo_location, cli_args.get("repository")
    )

    external_pipeline = get_external_pipeline_from_external_repo(
        external_repo,
        cli_args.get("pipeline"),
    )

    noprompt = cli_args.get("noprompt")

    pipeline_partition_set_names = {
        external_partition_set.name: external_partition_set
        for external_partition_set in external_repo.get_external_partition_sets()
        if external_partition_set.pipeline_name == external_pipeline.name
    }

    if not pipeline_partition_set_names:
        raise click.UsageError(
            "No partition sets found for pipeline `{}`".format(external_pipeline.name)
        )
    partition_set_name = cli_args.get("partition_set")
    if not partition_set_name:
        if len(pipeline_partition_set_names) == 1:
            partition_set_name = next(iter(pipeline_partition_set_names.keys()))
        elif noprompt:
            raise click.UsageError("No partition set specified (see option `--partition-set`)")
        else:
            partition_set_name = click.prompt(
                "Select a partition set to use for backfill: {}".format(
                    ", ".join(x for x in pipeline_partition_set_names.keys())
                )
            )

    partition_set = pipeline_partition_set_names.get(partition_set_name)

    if not partition_set:
        raise click.UsageError("No partition set found named `{}`".format(partition_set_name))

    run_tags = get_tags_from_args(cli_args)

    repo_handle = RepositoryHandle(
        repository_name=external_repo.name,
        repository_location=repo_location,
    )

    try:
        partition_names_or_error = repo_location.get_external_partition_names(
            repo_handle,
            partition_set_name,
        )
    except Exception:  # pylint: disable=broad-except
        error_info = serializable_error_info_from_exc_info(sys.exc_info())
        raise DagsterBackfillFailedError(
            "Failure fetching partition names for {partition_set_name}: {error_message}".format(
                partition_set_name=partition_set_name,
                error_message=error_info.message,
            ),
            serialized_error_info=error_info,
        )

    partition_names = gen_partition_names_from_args(
        partition_names_or_error.partition_names, cli_args
    )

    # Print backfill info
    print_fn("\n     Pipeline: {}".format(external_pipeline.name))
    print_fn("Partition set: {}".format(partition_set_name))
    print_fn("   Partitions: {}\n".format(print_partition_format(partition_names, indent_level=15)))

    # Confirm and launch
    if noprompt or click.confirm(
        "Do you want to proceed with the backfill ({} partitions)?".format(len(partition_names))
    ):

        print_fn("Launching runs... ")

        backfill_id = make_new_backfill_id()
        backfill_job = PartitionBackfill(
            backfill_id=backfill_id,
            partition_set_origin=partition_set.get_external_origin(),
            status=BulkActionStatus.REQUESTED,
            partition_names=partition_names,
            from_failure=False,
            reexecution_steps=None,
            tags=run_tags,
            backfill_timestamp=pendulum.now("UTC").timestamp(),
        )
        try:
            partition_execution_data = (
                repo_location.get_external_partition_set_execution_param_data(
                    repository_handle=repo_handle,
                    partition_set_name=partition_set_name,
                    partition_names=partition_names,
                )
            )
        except Exception:  # pylint: disable=broad-except
            error_info = serializable_error_info_from_exc_info(sys.exc_info())
            instance.add_backfill(
                backfill_job.with_status(BulkActionStatus.FAILED).with_error(error_info)
            )
            return print_fn("Backfill failed: {}".format(error_info))

        assert isinstance(partition_execution_data, ExternalPartitionSetExecutionParamData)

        for partition_data in partition_execution_data.partition_data:
            pipeline_run = create_backfill_run(
                instance,
                repo_location,
                external_pipeline,
                partition_set,
                backfill_job,
                partition_data,
            )
            if pipeline_run:
                instance.submit_run(pipeline_run.run_id, workspace)

        instance.add_backfill(backfill_job.with_status(BulkActionStatus.COMPLETED))

        print_fn("Launched backfill job `{}`".format(backfill_id))

    else:
        print_fn("Aborted!")
예제 #15
0
def test_partial_backfill(external_repo_context):
    with instance_for_context(external_repo_context) as (
            instance,
            grpc_server_registry,
            external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set(
            "partial_partition_set")

        # create full runs, where every step is executed
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="full",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        assert instance.get_runs_count() == 0
        list(
            execute_backfill_iteration(
                instance, grpc_server_registry,
                get_default_daemon_logger("BackfillDaemon")))
        wait_for_all_runs_to_start(instance)

        assert instance.get_runs_count() == 3
        runs = instance.get_runs()
        three, two, one = runs

        assert one.tags[BACKFILL_ID_TAG] == "full"
        assert one.tags[PARTITION_NAME_TAG] == "one"
        assert one.status == PipelineRunStatus.SUCCESS
        assert step_succeeded(instance, one, "step_one")
        assert step_succeeded(instance, one, "step_two")
        assert step_succeeded(instance, one, "step_three")

        assert two.tags[BACKFILL_ID_TAG] == "full"
        assert two.tags[PARTITION_NAME_TAG] == "two"
        assert two.status == PipelineRunStatus.SUCCESS
        assert step_succeeded(instance, two, "step_one")
        assert step_succeeded(instance, two, "step_two")
        assert step_succeeded(instance, two, "step_three")

        assert three.tags[BACKFILL_ID_TAG] == "full"
        assert three.tags[PARTITION_NAME_TAG] == "three"
        assert three.status == PipelineRunStatus.SUCCESS
        assert step_succeeded(instance, three, "step_one")
        assert step_succeeded(instance, three, "step_two")
        assert step_succeeded(instance, three, "step_three")

        # delete one of the runs, the partial reexecution should still succeed because the steps
        # can be executed independently, require no input/output config
        instance.delete_run(one.run_id)
        assert instance.get_runs_count() == 2

        # create partial runs
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="partial",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=["step_one"],
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        list(
            execute_backfill_iteration(
                instance, grpc_server_registry,
                get_default_daemon_logger("BackfillDaemon")))
        wait_for_all_runs_to_start(instance)

        assert instance.get_runs_count() == 5
        partial_filter = PipelineRunsFilter(tags={BACKFILL_ID_TAG: "partial"})
        assert instance.get_runs_count(filters=partial_filter) == 3
        runs = instance.get_runs(filters=partial_filter)
        three, two, one = runs

        assert one.status == PipelineRunStatus.SUCCESS
        assert step_succeeded(instance, one, "step_one")
        assert step_did_not_run(instance, one, "step_two")
        assert step_did_not_run(instance, one, "step_three")

        assert two.status == PipelineRunStatus.SUCCESS
        assert step_succeeded(instance, two, "step_one")
        assert step_did_not_run(instance, two, "step_two")
        assert step_did_not_run(instance, two, "step_three")

        assert three.status == PipelineRunStatus.SUCCESS
        assert step_succeeded(instance, three, "step_one")
        assert step_did_not_run(instance, three, "step_two")
        assert step_did_not_run(instance, three, "step_three")
예제 #16
0
def test_failure_backfill(external_repo_context):
    output_file = _failure_flag_file()
    with instance_for_context(external_repo_context) as (
            instance,
            grpc_server_registry,
            external_repo,
    ):
        external_partition_set = external_repo.get_external_partition_set(
            "conditionally_fail_partition_set")
        instance.add_backfill(
            PartitionBackfill(
                backfill_id="shouldfail",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=False,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))
        assert instance.get_runs_count() == 0

        try:
            touch_file(output_file)
            list(
                execute_backfill_iteration(
                    instance, grpc_server_registry,
                    get_default_daemon_logger("BackfillDaemon")))
            wait_for_all_runs_to_start(instance)
        finally:
            os.remove(output_file)

        assert instance.get_runs_count() == 3
        runs = instance.get_runs()
        three, two, one = runs
        assert one.tags[BACKFILL_ID_TAG] == "shouldfail"
        assert one.tags[PARTITION_NAME_TAG] == "one"
        assert one.status == PipelineRunStatus.FAILURE
        assert step_succeeded(instance, one, "always_succeed")
        assert step_failed(instance, one, "conditionally_fail")
        assert step_did_not_run(instance, one, "after_failure")

        assert two.tags[BACKFILL_ID_TAG] == "shouldfail"
        assert two.tags[PARTITION_NAME_TAG] == "two"
        assert two.status == PipelineRunStatus.FAILURE
        assert step_succeeded(instance, two, "always_succeed")
        assert step_failed(instance, two, "conditionally_fail")
        assert step_did_not_run(instance, two, "after_failure")

        assert three.tags[BACKFILL_ID_TAG] == "shouldfail"
        assert three.tags[PARTITION_NAME_TAG] == "three"
        assert three.status == PipelineRunStatus.FAILURE
        assert step_succeeded(instance, three, "always_succeed")
        assert step_failed(instance, three, "conditionally_fail")
        assert step_did_not_run(instance, three, "after_failure")

        instance.add_backfill(
            PartitionBackfill(
                backfill_id="fromfailure",
                partition_set_origin=external_partition_set.
                get_external_origin(),
                status=BulkActionStatus.REQUESTED,
                partition_names=["one", "two", "three"],
                from_failure=True,
                reexecution_steps=None,
                tags=None,
                backfill_timestamp=pendulum.now().timestamp(),
            ))

        assert not os.path.isfile(_failure_flag_file())
        list(
            execute_backfill_iteration(
                instance, grpc_server_registry,
                get_default_daemon_logger("BackfillDaemon")))
        wait_for_all_runs_to_start(instance)

        assert instance.get_runs_count() == 6
        from_failure_filter = PipelineRunsFilter(
            tags={BACKFILL_ID_TAG: "fromfailure"})
        assert instance.get_runs_count(filters=from_failure_filter) == 3

        runs = instance.get_runs(filters=from_failure_filter)
        three, two, one = runs

        assert one.tags[BACKFILL_ID_TAG] == "fromfailure"
        assert one.tags[PARTITION_NAME_TAG] == "one"
        assert one.status == PipelineRunStatus.SUCCESS
        assert step_did_not_run(instance, one, "always_succeed")
        assert step_succeeded(instance, one, "conditionally_fail")
        assert step_succeeded(instance, one, "after_failure")

        assert two.tags[BACKFILL_ID_TAG] == "fromfailure"
        assert two.tags[PARTITION_NAME_TAG] == "two"
        assert two.status == PipelineRunStatus.SUCCESS
        assert step_did_not_run(instance, one, "always_succeed")
        assert step_succeeded(instance, one, "conditionally_fail")
        assert step_succeeded(instance, one, "after_failure")

        assert three.tags[BACKFILL_ID_TAG] == "fromfailure"
        assert three.tags[PARTITION_NAME_TAG] == "three"
        assert three.status == PipelineRunStatus.SUCCESS
        assert step_did_not_run(instance, one, "always_succeed")
        assert step_succeeded(instance, one, "conditionally_fail")
        assert step_succeeded(instance, one, "after_failure")