Repository navigation
feat(coordinator)!: plan and run reads through the list of sources - #659
Merged
Merged
Conversation
This was referenced Nov 4, 2026
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 4, 2026 13:16
c6783de to
fd90c6e
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 4, 2026 13:34
fd90c6e to
e1df089
Compare
This was referenced Nov 4, 2026
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 4, 2026 14:58
e1df089 to
f724063
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 4, 2026 15:27
f724063 to
33b2ecd
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
2 times, most recently
from
November 4, 2026 20:02
2d6a1a0 to
7fc9277
Compare
This was referenced Nov 4, 2026
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
2 times, most recently
from
November 7, 2026 16:27
12542d4 to
fde254d
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 7, 2026 17:40
fde254d to
e7927e7
Compare
Contributor
Author
|
re top level comment: |
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 7, 2026 22:40
e7927e7 to
c86b94d
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 9, 2026 13:56
c86b94d to
38ecf35
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 10, 2026 14:39
38ecf35 to
600e64c
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 10, 2026 15:50
600e64c to
77877e0
Compare
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 10, 2026 16:24
77877e0 to
3a788f2
Compare
A read now has its own coordinator, in timenet.coordinator.read. plan_read() returns the plan of a read without running it. read_release() runs the plan and opens the release with its payload sources. The client uses read_release() only for a remote registry so far. A read opens a release where it is. The first source that provides the release gives a ReadStep, and the read copies nothing. Each payload source resolves on its own through the same list, at its exact version. So a release and its payload sources can come from different registries. The pins of the release must match each payload source. The read and the build share one planner. A read is a fourth outcome of the walk of the build planner, next to no step, a copy and a build. The walk takes needed_in_local_registry: a build needs a complete copy in the store, and a read needs only a source that serves the release. If only InstalledConnectors() provides a release, the walk plans its build into the store, with the whole list as the sources of its parents. If a build also needs a release that the read found in a registry, the release goes into the store, and the read opens it there. A read that needs a build without a store raises TimeFValidationError. Before any step runs, the plan checks the pins of each payload source. Then it checks the size of each file of each release that it reads from a local registry. A copy that a build needs can still repair a damaged copy that the read found first. A damaged copy in the store also fails a read that no registry serves. So the read never falls through to a later source and never builds over the damage. The plan and the builds that it plans share one set of answers and manifests. read_release() opens each release with the manifest that the plan got. So a remote read fetches each manifest once. The walk takes the answer for the requested release, so a read of the latest version does not ask again for the exact version. BaseRegistry gets open_release(), which opens one exact release without its payload sources. It takes the manifest if the caller has it, and it may use that manifest. A local registry checks the size of each file. A remote registry uses a complete cached copy, else the remote files. open_cached_or_remote_release() holds that one-release open. Step is now ReadStep | CopyStep | BuildStep, and run_plan() runs nothing for a read step. The planner shares Lookups, plan_steps() and describe_searched_sources() with the read coordinator. BaseRegistry.open_version() goes away, with its implementations and open_cached_or_remote(). open_release() and download_release() handle one release without its payload sources, and copy_release() copies a release with them. A read of a release with its payload sources goes through the read coordinator. A read can need one release twice. For example, a child reads P1 and P2, and the card of P1 declares P2. The release then has one step, and its build must match the pins of each reader. If two readers pin one file of the release as different files, no build can match both, and the plan raises TimeFFormatError. A cycle through the requested release names that release first. The plan builds a release with the InstalledBuilder that its lookup read, so it reads the card of the connector once. The error for a missing payload source names the sources in the same way as the error of the plan, with the version that the installed connector builds. BREAKING CHANGE: BaseRegistry has a new abstract method, open_release(). A registry of another package must implement it. The abstract LazyReadRegistry._open_remote_version() takes an optional manifest. BaseRegistry.open_version() is gone from every registry. To read a release with its payload sources from one registry, use TimeNet(sources=[registry]).open(). Part of TNET-157.
Say only what a caller of the read plan and of open_release() needs to know. Part of TNET-157.
Shorter docstrings for the code that this change adds or changes. Part of TNET-157.
Drop tests that cannot fail or repeat other tests, and sharpen the rest. Part of TNET-157.
karhu
force-pushed
the
tnet-157/11-read-coordinator
branch
from
November 10, 2026 17:41
3a788f2 to
a2a0fd1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Stack
This stack covers refactoring the internal logic of how releases are resolved during read, download & build, in particular also in the context of parent releases / parent datasets. On top of that it refactors the public TimeNet APIs and CLI interfaces around these actions, to streamline the behavior across them.
This PR
Adds a coordinator for reads, with
plan_read()andread_release(). The next PR moves the client onto it.Details
A build plans and runs through one coordinator since #652, and it gets its parents from an ordered list of sources since #658 (TNET-157). A read still has its own code path in the client. This PR gives reads a coordinator of their own. The next PR moves the client onto it.
timenet.coordinator.readhasplan_read()andread_release().plan_read()returns the plan of a read without running it.read_release()runs the plan and opens the release with its payload sources.ReadStep, and the read copies nothing. Each payload source resolves on its own through the same list, at its exact version. So a release and its payload sources can come from different registries.InstalledConnectors()provides a release, the plan builds it into the store, as a build does. A copy or a build of a release replaces a read of it, and the read then opens the release from the store. This also holds when a build in the same plan needs a release that the read found in a registry: the release goes into the store, and the read opens it there._Graph.visit(), next to no step, a copy and a build.visit()takesneeded_in_local_registry. It is true for builds and downloads, which need a complete copy in the store, and false for reads, where a source that serves the release is enough.ReadStep(release, registry, depends_on)joinsCopyStepandBuildStepin theStepunion.run_plan()has an arm for it that runs nothing.BaseRegistrygetsopen_release(), which opens one exact release without its payload sources. It can take the manifest from the caller. So a remote read fetches each manifest once.open_version()goes away from every registry, and so doesdependencies.open_cached_or_remote().open_release()anddownload_release()handle one release without its payload sources, andcopy_release()copies a release with them. A read of a release with its payload sources goes through the read coordinator.Design decisions
TimeFFormatError.InstalledBuilderthat its lookup read, so it reads the card of each connector once.Breaking changes
BaseRegistryhas a new abstract method,open_release(). A registry of another package must implement it.LazyReadRegistry._open_remote_version()takes an optional manifest.BaseRegistry.open_version()is gone from every registry. To read a release with its payload sources from one registry, use the client, for exampleTimeNet(registry).open(). From feat(client)!: take an ordered list of sources #661 on, the call isTimeNet(sources=[registry]).open().Stack
Changes later in the stack:
open(),load()andopen_torch()ontoread_release().Merge message