Skip to content

Commit eb7352f

Browse files
akhileshhclaude
andcommitted
fix(meshing): mirror the v1 manifest response in v2
v2 emits each fragment identical to v1 (seg id prepended when asked) and honors return_seg_ids, differing only by grouping fragments under their bucket key, so the client reuses its v1 handling unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 5face36 commit eb7352f

3 files changed

Lines changed: 38 additions & 16 deletions

File tree

pychunkedgraph/app/meshing/common.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,10 @@ def manifest_response(cg, args):
138138

139139
if manifest_version >= 2:
140140
mm = MeshMeta(cg)
141-
initial, dynamic = v2.to_v2_groups(
142-
seg_ids, fragments, seg_id_in_fragment=not verify
143-
)
141+
initial, dynamic = v2.to_v2_groups(seg_ids, fragments, prepend_seg_ids)
144142
resp = v2.assemble(mm.initial_path, mm.dynamic_path, initial, dynamic)
143+
if return_seg_ids:
144+
resp["seg_ids"] = seg_ids
145145
else:
146146
resp = {"fragments": fragments}
147147
if prepend_seg_ids:

pychunkedgraph/meshing/manifest/v2.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,17 @@ def requested_manifest_version(accept_header, default: int = 1) -> int:
3131
return default
3232

3333

34-
def to_v2_groups(node_ids, fragments, seg_id_in_fragment: bool):
35-
"""Split the v1 ``(node_ids, fragments)`` output into
36-
``(initial_frags, dynamic_frags)`` for the v2 format.
34+
def to_v2_groups(node_ids, fragments, prepend_seg_ids):
35+
"""Group v1 fragments into ``(initial, dynamic)`` by the leading ``~`` marker.
3736
38-
Initial (sharded) fragments are marked by a leading ``~``; the marker is
39-
dropped and the seg id ensured as the leading field. Dynamic fragments carry
40-
no marker and already lead with the seg id. ``seg_id_in_fragment`` is True
41-
when the initial fragments already embed the seg id (speculative), False when
42-
it must be prepended (verified).
37+
Each fragment is emitted exactly as the v1 manifest would (seg id prepended
38+
when requested); only the initial-vs-dynamic grouping is added. The raw ``~``
39+
selects the group, matching v1's ``~<segid>:<fragment>``.
4340
"""
4441
initial, dynamic = [], []
4542
for node_id, frag in zip(node_ids, fragments):
46-
if frag.startswith("~"):
47-
body = frag[1:]
48-
initial.append(body if seg_id_in_fragment else f"{node_id}:{body}")
49-
else:
50-
dynamic.append(frag)
43+
out = f"~{node_id}:{frag}" if prepend_seg_ids else frag
44+
(initial if frag.startswith("~") else dynamic).append(out)
5145
return initial, dynamic
5246

5347

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Tests for pychunkedgraph.meshing.manifest.v2."""
2+
3+
from pychunkedgraph.meshing.manifest.v2 import assemble, to_v2_groups
4+
5+
6+
class TestToV2Groups:
7+
def test_prepend_matches_v1_grouped_by_type(self):
8+
"""With prepend_seg_ids each fragment is v1's ``~<segid>:<frag>``; grouping
9+
is by the raw ~ (initial/sharded) vs no-~ (dynamic/whole-file)."""
10+
node_ids = [386, 529]
11+
frags = ["~5/774017-0.shard:74809813:4532", "529:0:90112-98304"]
12+
ini, dyn = to_v2_groups(node_ids, frags, prepend_seg_ids=True)
13+
assert ini == ["~386:~5/774017-0.shard:74809813:4532"]
14+
assert dyn == ["~529:529:0:90112-98304"]
15+
16+
def test_no_prepend_keeps_raw(self):
17+
ini, dyn = to_v2_groups(
18+
[386, 529], ["~a.shard:1:2", "529:0:bbox"], prepend_seg_ids=False
19+
)
20+
assert ini == ["~a.shard:1:2"]
21+
assert dyn == ["529:0:bbox"]
22+
23+
def test_assemble_groups_under_bucket(self):
24+
resp = assemble(
25+
"gs://b/initial", "gs://b/dynamic", ["~386:~a.shard:1:2"], ["~529:529:0:y"]
26+
)
27+
assert resp["fragments"]["gs://b/initial"]["fragments"] == ["~386:~a.shard:1:2"]
28+
assert resp["manifest_version"] == 2

0 commit comments

Comments
 (0)