Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d21c676
[feat] add kv_link so keys can read another key's fields without copies
OutstanderWang Oct 16, 2026
dd244ae
[fix] refuse kv_link to a source that is being cleared
OutstanderWang Oct 16, 2026
6fa7ac1
[fix] reject duplicate keys in kv_link
OutstanderWang Oct 16, 2026
53b5e72
[perf] index kv_link links by source so clear checks scale with the c…
OutstanderWang Oct 16, 2026
7f6f570
[fix] linked keys follow their source's readiness and shape
OutstanderWang Oct 16, 2026
3fb2f14
[fix] refuse kv_update on fields linked by kv_link with a clear error
OutstanderWang Oct 16, 2026
3230d9f
[fix] refuse kv_link that relinks a source key or links a key to itself
OutstanderWang Oct 16, 2026
28fe241
[fix] a put through BatchMeta drops its local links on the written fi…
OutstanderWang Oct 16, 2026
bf8cce6
[feat] kv_describe reports the fields each key links by kv_link
OutstanderWang Oct 16, 2026
7b3172a
[doc] document and test that data_parser refuses fields linked by kv_…
OutstanderWang Oct 16, 2026
c1275d6
[doc] describe kv_link readiness, kv_update and source-sample behavior
OutstanderWang Oct 16, 2026
579e99c
[fix] load controller checkpoints saved before kv_link
OutstanderWang Oct 16, 2026
bd4d9b8
[fix] refuse dumping a linked source field that is not finalized
OutstanderWang Oct 16, 2026
7885203
[fix] BatchMeta.union takes links from the side whose fields win
OutstanderWang Oct 16, 2026
96ea8da
[feat] balance each partition's rows across SimpleStorage units
OutstanderWang Oct 19, 2026
ee97937
[feat] kv_link reads shared payloads from a __public__ partition
OutstanderWang Oct 19, 2026
31e606a
feat: add kv_clear_unlinked_public to free public keys no key links to
OutstanderWang Oct 19, 2026
b3849e9
[fix] drop links to public rows released while a racing put made them…
OutstanderWang Oct 19, 2026
c2048cb
[fix] kv_link validates field types before creating keys
OutstanderWang Oct 19, 2026
5837879
[test] controller checkpoints restore kv_link links and their clear g…
OutstanderWang Oct 19, 2026
4c441ca
[fix] repeated keys keep their own parser_args when reading
OutstanderWang Oct 20, 2026
8fdf3ff
[fix] bump the dump format to 5 so older readers reject dumps with links
OutstanderWang Oct 20, 2026
5162c4f
[fix] kv_link refuses an empty key list
OutstanderWang Oct 20, 2026
78134b5
[fix] kv_link refuses fields a key already stores itself
OutstanderWang Oct 20, 2026
ae87d25
[fix] check the SimpleStorage backend in TransferQueueClient.kv_link
OutstanderWang Oct 20, 2026
b0d2acb
[fix] load relinks before writing payloads so an incompatible link wr…
OutstanderWang Oct 20, 2026
bba58db
[feat] a linked public key is read-only until no key links to it
OutstanderWang Oct 20, 2026
11d6a38
[feat] puts refuse fields linked by kv_link instead of replacing the …
OutstanderWang Oct 20, 2026
514ee42
[feat] kv_describe lists linked fields as readable, and link refusals…
OutstanderWang Oct 20, 2026
2e812ec
[feat] kv_clear_unlinked_public frees only public keys that were link…
OutstanderWang Oct 20, 2026
1166b53
[feat] kv_link takes one public key per key to link a batch in one at…
OutstanderWang Oct 20, 2026
c8e999a
[fix] kv_link merges into a field whose schema is non-tensor
OutstanderWang Oct 20, 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