Hadron / Hadron/carthage

Add ready_stage for always-run setup-task synchronization points

Open
#146 0 comments 0 reactions 1 assignee Claimed by @hartmans View on GitHub
Dominant language
Python
Stars
11
Forks
8
Avg merge
9h 26m
Merged PRs (30d)
6

Description

## Summary

Add a `ready_stage` abstraction alongside `setup_task`. A ready stage is an ordered point in a setup-task chain that always executes when traversal reaches it, rather than being skipped based on stamps, source time, hashes, invalidators, or `check_completed`.

The main use case is a reliable cross-object synchronization point: a dependency on another object's ready stage must run that stage every time, after first running any earlier setup tasks on the related object whose normal `should_run_task()` checks say they need to run.

## Proposed semantics

A `ready_stage` should be usable in a `SetupTaskMixin` class similarly to a `setup_task`, and participate in the same ordering model (`order` / `before` and class/MRO collection).

When `run_setup_tasks(stop_after=stage)` reaches a ready stage:

1. Earlier setup tasks are considered in order and run only when their existing `should_run_task()` logic says they should run.
2. The ready stage itself always runs.
3. Traversal stops at the stage when it is the `stop_after` target; later tasks are not considered.
4. Exceptions propagate normally, and the standard task start/run/fail instrumentation remains useful.
5. Each successful run has a completion time that can participate in dependency-last-run propagation.

A `cross_object_dependency` whose target is a ready stage should always call the related object's task chain through that stage. This should not depend on whether the stage has previously run or has a stamp. After the stage completes, later tasks in the depending object should see the stage's completion time, so they rerun when appropriate.

This is distinct from `ready=True` on `cross_object_dependency`: that option brings the entire related `AsyncInjectable` to ready before checking the target task, while a ready stage is an explicit ordered barrier within the related setup-task chain.

## Motivation

Today, `cross_object_dependency.check_completed_func()` asks the target wrapper's `should_run_task()` whether work is needed and calls `relationship.run_setup_tasks(stop_after=task)` only when that answer is true. A conventional `setup_task` therefore cannot express “always establish this stage now,” because its persisted completion mechanisms make later evaluations skip it.

A stage boundary is useful when earlier tasks remain incremental but some finalization/refresh step must always occur before another object evaluates or executes its own dependent work.

## API considerations

- Export `ready_stage` from `carthage.setup_tasks` alongside `setup_task`.
- Prefer a distinct wrapper type or an explicit capability on `TaskWrapperBase`, so `cross_object_dependency` can recognize stage semantics without special-casing function names.
- Define how direct calls to a bound ready-stage method behave; the least surprising behavior is the same as a bound setup task—execute the stage and emit normal task events.
- Inspection should identify a ready stage as always runnable without invoking it as a side effect.
- Preserve cycle detection and existing `ready=True` behavior.

## Suggested tests

- A normal traversal runs only invalidated prior setup tasks, always runs the stage, and does not run tasks after `stop_after=stage`.
- Repeating the traversal skips still-valid prior tasks but runs the stage again.
- A cross-object dependency on the stage performs that same traversal even after a previous successful run.
- The stage's new completion time invalidates the appropriate later tasks in the depending object.
- Stage failure prevents dependent tasks from running and is observable through task-failure instrumentation.
- Ordering, inheritance, dry-run, readonly, and concurrent/cyclic dependency behavior are explicitly covered or documented.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.