Skip to content

Commit ac404f8

Browse files
committed
fix(data): enforce semantic chunk claims
1 parent 936d700 commit ac404f8

4 files changed

Lines changed: 476 additions & 162 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from __future__ import annotations
2+
3+
import sqlite3
4+
import sys
5+
from pathlib import Path
6+
7+
8+
MLX_ROOT = Path(__file__).resolve().parents[1]
9+
CLANG_INDEXER = MLX_ROOT / "tools" / "clang_indexer"
10+
if str(CLANG_INDEXER) not in sys.path:
11+
sys.path.insert(0, str(CLANG_INDEXER))
12+
13+
14+
def test_chunk_claims_are_wal_backed_and_count_limited(tmp_path):
15+
from dedup_store import DedupStore
16+
17+
db = tmp_path / "dedup.sqlite"
18+
first = DedupStore(str(db), near=False, commit_every=1)
19+
second = DedupStore(str(db), near=False, commit_every=1)
20+
try:
21+
assert first.conn.execute("PRAGMA journal_mode").fetchone()[0] == "wal"
22+
23+
assert first.claim_chunk_tokens([10, 20, 30], namespace="strict") is True
24+
assert second.claim_chunk_tokens([10, 20, 30], namespace="strict") is False
25+
26+
assert first.claim_chunk_tokens([10, 20, 30], namespace="repeat3", max_count=3)
27+
assert second.claim_chunk_tokens([10, 20, 30], namespace="repeat3", max_count=3)
28+
assert first.claim_chunk_tokens([10, 20, 30], namespace="repeat3", max_count=3)
29+
assert not second.claim_chunk_tokens(
30+
[10, 20, 30],
31+
namespace="repeat3",
32+
max_count=3,
33+
)
34+
finally:
35+
first.close()
36+
second.close()
37+
38+
conn = sqlite3.connect(db)
39+
try:
40+
rows = dict(
41+
conn.execute(
42+
"SELECT namespace, claim_count FROM chunk_claims ORDER BY namespace"
43+
).fetchall()
44+
)
45+
finally:
46+
conn.close()
47+
48+
assert rows == {"repeat3": 3, "strict": 1}

tools/clang_indexer/dedup_store.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ def _init_schema(self) -> None:
185185
self._execute_write(
186186
"CREATE TABLE IF NOT EXISTS dedup_meta (key TEXT PRIMARY KEY, val INTEGER)"
187187
)
188+
self._execute_write(
189+
"CREATE TABLE IF NOT EXISTS chunk_claims ("
190+
"namespace TEXT NOT NULL, "
191+
"hash BLOB NOT NULL, "
192+
"claim_count INTEGER NOT NULL, "
193+
"PRIMARY KEY(namespace, hash))"
194+
)
188195
# next doc_id counter for near-dup docs.
189196
self._execute_write(
190197
"INSERT OR IGNORE INTO dedup_meta (key, val) VALUES ('next_doc_id', 0)"
@@ -369,6 +376,44 @@ def seen_near_tokens(self, token_ids: Sequence[int]) -> bool:
369376
self._mark_pending()
370377
return False
371378

379+
def claim_chunk_tokens(
380+
self,
381+
token_ids: Sequence[int],
382+
*,
383+
namespace: str = "train_chunk",
384+
max_count: int = 1,
385+
) -> bool:
386+
"""Claim one semantic training chunk by its tokenized body.
387+
388+
This is separate from the ``exact``/``minhash`` dedup tables. Exact/near
389+
dedup decides whether a function may be emitted as a root document;
390+
chunk claims decide whether that already-tokenized function/class/type
391+
body may appear anywhere in the training stream. The unit of ownership is
392+
still the caller-provided semantic chunk; the hash is only the SQLite key.
393+
394+
Returns True when this call successfully claimed one slot. Returns False
395+
when the tokenized chunk has already reached ``max_count`` in ``namespace``.
396+
The write is committed immediately so concurrent conveyor processes see
397+
the claim before they assemble overlapping 1k/2k/4k/8k buckets.
398+
"""
399+
if max_count < 1:
400+
raise ValueError("claim_chunk_tokens requires max_count >= 1")
401+
if not namespace:
402+
raise ValueError("claim_chunk_tokens requires a non-empty namespace")
403+
h = _sha1_tokens(token_ids)
404+
cur = self._execute_write(
405+
"INSERT INTO chunk_claims(namespace, hash, claim_count) "
406+
"VALUES (?, ?, 1) "
407+
"ON CONFLICT(namespace, hash) DO UPDATE SET "
408+
"claim_count = claim_count + 1 "
409+
"WHERE claim_count < ?",
410+
(namespace, h, int(max_count)),
411+
)
412+
# Claims are coordination records, not buffered dedup rows. Commit them
413+
# immediately so other WAL connections see the slot before emitting docs.
414+
self.commit()
415+
return cur.rowcount == 1
416+
372417
# ----------------------------------------------------------------- #
373418
def _load_minhash(self, doc_id: int):
374419
row = self.conn.execute(

0 commit comments

Comments
 (0)