Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0150f92
[feat] add kv_link so keys can read another key's fields without copies
OutstanderWang Oct 16, 2026
28ab8e1
[fix] refuse kv_link to a source that is being cleared
OutstanderWang Oct 16, 2026
8d7380e
[fix] reject duplicate keys in kv_link
OutstanderWang Oct 16, 2026
c79e95f
[perf] index kv_link links by source so clear checks scale with the c…
OutstanderWang Oct 16, 2026
260e1a0
[fix] linked keys follow their source's readiness and shape
OutstanderWang Oct 16, 2026
3d1334f
[fix] refuse kv_update on fields linked by kv_link with a clear error
OutstanderWang Oct 16, 2026
a8b9053
[fix] refuse kv_link that relinks a source key or links a key to itself
OutstanderWang Oct 16, 2026
35854fa
[fix] a put through BatchMeta drops its local links on the written fi…
OutstanderWang Oct 16, 2026
f9baa65
[feat] kv_describe reports the fields each key links by kv_link
OutstanderWang Oct 16, 2026
e5b2454
[doc] document and test that data_parser refuses fields linked by kv_…
OutstanderWang Oct 16, 2026
1990f79
[doc] describe kv_link readiness, kv_update and source-sample behavior
OutstanderWang Oct 16, 2026
7bb47f8
[fix] load controller checkpoints saved before kv_link
OutstanderWang Oct 16, 2026
e2c4ec5
[fix] refuse dumping a linked source field that is not finalized
OutstanderWang Oct 16, 2026
25dbbbd
[fix] BatchMeta.union takes links from the side whose fields win
OutstanderWang Oct 16, 2026
2d99b29
[feat] balance each partition's rows across SimpleStorage units
OutstanderWang Oct 19, 2026
498d7d1
[feat] kv_link reads shared payloads from a __public__ partition
OutstanderWang Oct 19, 2026
ccfe6bb
feat: add kv_clear_unlinked_public to free public keys no key links to
OutstanderWang Oct 19, 2026
88d7ee2
[fix] drop links to public rows released while a racing put made them…
OutstanderWang Oct 19, 2026
0befabf
[fix] kv_link validates field types before creating keys
OutstanderWang Oct 19, 2026
bb0cc15
[test] controller checkpoints restore kv_link links and their clear g…
OutstanderWang Oct 19, 2026
c2addb8
[fix] repeated keys keep their own parser_args when reading
OutstanderWang Oct 20, 2026
674f388
[fix] bump the dump format to 5 so older readers reject dumps with links
OutstanderWang Oct 20, 2026
50cf460
[fix] kv_link refuses an empty key list
OutstanderWang Oct 20, 2026
b8d560d
[fix] kv_link refuses fields a key already stores itself
OutstanderWang Oct 20, 2026
734ba88
[fix] check the SimpleStorage backend in TransferQueueClient.kv_link
OutstanderWang Oct 20, 2026
915c065
[fix] load relinks before writing payloads so an incompatible link wr…
OutstanderWang Oct 20, 2026
e485b7b
[feat] a linked public key is read-only until no key links to it
OutstanderWang Oct 20, 2026
7d030ff
[feat] puts refuse fields linked by kv_link instead of replacing the …
OutstanderWang Oct 20, 2026
91d73a2
[feat] kv_describe lists linked fields as readable, and link refusals…
OutstanderWang Oct 20, 2026
8fa7890
[feat] kv_clear_unlinked_public frees only public keys that were link…
OutstanderWang Oct 20, 2026
1372eb9
[feat] kv_link takes one public key per key to link a batch in one at…
OutstanderWang Oct 20, 2026
9e371d0
[fix] kv_link merges into a field whose schema is non-tensor
OutstanderWang Oct 20, 2026
3304345
[feat] kv_exists reports ready fields without logging; kv_clear_unlin…
OutstanderWang Oct 22, 2026
7f44d64
[feat] BatchMeta rows can link, write and clear PUBLIC_PARTITION rows…
OutstanderWang Oct 23, 2026
a0c3397
[feat] kv_batch_get data_parser applies to linked fields on the publi…
OutstanderWang Oct 23, 2026
1c48464
[chore] pass the docstring sanity check
OutstanderWang Oct 23, 2026
a22f20b
[fix] type _link_conflicts rows as a Sequence so mypy accepts list[int]
OutstanderWang Oct 23, 2026
590d873
[fix] linked fields from one public row are read together; link keeps…
OutstanderWang Oct 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/data_dump.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ These count application reads, not filesystem read-ahead or physical disk traffi

## Format and compatibility

Dumps use `format_version: 4`. Version 4 adds each row's `unfinalized` fields, which
restore keeps hidden. This build also reads version 3 dumps, whose fields restore as
ready. Builds that only read version 3 reject version 4 dumps instead of exposing
hidden fields. The layout:
Dumps use `format_version: 5`. Version 5 adds each row's `links`, the fields it reads
from `PUBLIC_PARTITION` keys through `kv_link`, recorded by public key name: load
relinks to whatever those keys hold then, so load their dump first. Version 4 added `unfinalized`, the
fields restore keeps hidden. This build also reads versions 3 and 4: version 4 rows
have no links, and version 3 fields restore as ready. Older builds reject newer dumps
instead of dropping linked fields or exposing hidden ones. The layout:

```text
dump_info.json
Expand Down
13 changes: 8 additions & 5 deletions tests/e2e/test_data_dump_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,18 +272,21 @@ def concat(old, new):
retrieved = tq.kv_batch_get(keys="u1", partition_id=partition_id, select_fields="response")
_assert_rows_equal(retrieved["response"], [torch.tensor([1, 2, 3])])

def test_restores_a_version_3_dump_as_ready(self, tq_system, dump_dir, controller):
partition_id = "d_version3"
@pytest.mark.parametrize("version", [3, 4])
def test_restores_an_older_dump_as_ready(self, tq_system, dump_dir, controller, version):
partition_id = f"d_version{version}"
_put_rows(partition_id, ["w0"])
tq.dump_data_by_key(dump_dir, ["w0"], partition_id)

# Rewrite it as version 3 wrote it: no ``unfinalized`` in the row index.
# Rewrite it as that version wrote it: no ``links``, and before 4 no ``unfinalized``.
row_index = _read_row_index(dump_dir)
del row_index["rows"]["w0"]["unfinalized"]
del row_index["rows"]["w0"]["links"]
if version == 3:
del row_index["rows"]["w0"]["unfinalized"]
torch.save(row_index, dump_dir / "row_index.pt")
info_path = dump_dir / "dump_info.json"
info = json.loads(info_path.read_text(encoding="utf-8"))
info["format_version"] = 3
info["format_version"] = version
info_path.write_text(json.dumps(info), encoding="utf-8")

ray.get(controller.clear_partition.remote(partition_id))
Expand Down
8 changes: 7 additions & 1 deletion tests/e2e/test_kv_interface_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,12 @@ def parse(data, args):
assert_nested_tensor_equal(retrieved["input_ids"], [input_ids[0, :2], input_ids[1, :3], input_ids[2, :1]])
assert_tensor_equal(retrieved["scores"], scores * 10)

# A repeated key reads its own argument, and the keys after it keep theirs.
retrieved = tq_api.kv_batch_get(
keys=["parse_0", "parse_0", "parse_1"], partition_id=partition_id, data_parser=parse, parser_args=[1, 2, 3]
)
assert_nested_tensor_equal(retrieved["input_ids"], [input_ids[0, :1], input_ids[0, :2], input_ids[1, :3]])

retrieved = tq_api.kv_batch_get(keys=keys, partition_id=partition_id)
assert_tensor_equal(retrieved["input_ids"], input_ids)
assert_tensor_equal(retrieved["scores"], scores)
Expand Down Expand Up @@ -1389,7 +1395,7 @@ def tokens_ready():
with pytest.raises(ValueError, match="not finalized"):
tq_api.kv_batch_get_by_meta(meta)
row = tq_api.kv_describe(keys=key, partition_id=partition_id)[key]
assert row == {"fields": ["prompt", "tokens"], "unfinalized": ["tokens"]}
assert row == {"fields": ["prompt", "tokens"], "unfinalized": ["tokens"], "links": {}}
with pytest.raises(RuntimeError, match="not found"):
tq_api.kv_describe(keys=[key, "absent"], partition_id=partition_id)

Expand Down
Loading
Loading