Sessions
Pin Project state with Snapshot, BranchHead and TableSession, and open Tables by address.
When a job reads frames@main, every read in that job should see the same
data, even if someone commits to main halfway through. The Rust SDK gives you
two types that pin the state once and keep it: a Snapshot holds one exact
Project commit, and a TableSession opens Tables by address against a default
Snapshot. Neither changes when the branch moves, so a training run or an audit
reads exactly what it read at the start.
This page covers the Rust types. For the task of pinning a branch or resolving a tag, see Select an exact state. For the commit and branch model, see Commits and branches.
Snapshot or TableSession
Use a TableSession to read. It accepts addresses
such as frames@main or frames@v019a…, and it pins each branch the first
time you name it, so every Table you open through it agrees.
Use a BranchHead to write. It is a Snapshot of a branch's head that
also records the branch, and a Commit starts from
it, because the commit must know which branch to publish to and which head it
read. A Snapshot also lists the resources at its commit.
You can move between them: snapshot.table_session() opens a session whose
default is the Snapshot's commit, and session.snapshot() returns the
session's default Snapshot. When the session's default is a branch,
session.head() returns its pinned BranchHead, which you can start a Commit
from; for an exact commit it returns None. After you publish,
session.with_head(head) starts a new session at the new head of the same
branch.
Open a Snapshot
| Call | Selects |
|---|---|
project.branch("main") | The current head of the branch, as a BranchHead. Commits from it publish to main. |
project.create_branch(name, commit_id) | A new branch at an existing commit, as a BranchHead. |
project.snapshot_at(commit_id) | An exact commit, as a read-only Snapshot. You cannot start a Commit from it, because it has no branch to publish to. |
client.project("demo") names a Project without a network request.
snapshot.commit_id() returns the pinned commit, snapshot.resources() lists
the resources at it, and snapshot.table(path) opens one Table by path. A
BranchHead has the same methods, and head.commit() starts a Commit.
Neither type refreshes. To see newer state, pin the branch again; publishing a Commit returns the branch's new head.
Open a Table session
Open a session from a Project with a branch name or a c<commit> reference as
its default, then open Tables by address:
let tables = client.project("demo")?.table_session("main").await?;
let table = tables.table("frames@main").await?;
let scan = table
.scan(ScanOptions {
limit: Some(100),
..Default::default()
})
.await?;
if let Some(address) = scan.resolved_address() {
println!("resolved address: {address}");
}
let mut batches = scan.into_stream();
let mut rows = 0;
while let Some(batch) = batches.next_batch().await {
rows += batch?.num_rows();
}TableSession::table accepts path, path@branch, path@c<commit>, and
path@v<version>. A bare path resolves in the session's default Snapshot. The
full grammar, including which references are IDs, is on
Resource addresses.
Branch pins and refresh
A session pins each branch head the first time it resolves that branch, and every later lookup of the same branch reuses that commit. Clones of a session share the same pins, even when lookups run concurrently, so you can hand clones to parallel tasks and they still agree.
TableSession::refresh() returns a new session with fresh pins. The old
session, and every Table and Scan you opened through it, keep the versions they
already selected.
Record what you read
A Table or Scan opened through an address reports the exact version it read
through resolved_address(), in the form path@v<version>. Store that string
with your results. Opening it later returns the same rows, as long as the path
still names that Table, because the session finds the Table by its path before
it selects the version.
client.table_by_id(resource_id, version_id) opens an exact version without a
path. Such a handle has no resolved address; it reports its IDs through
identity() instead.