mlx-model-explorer / tests /test_sink.py
codelion's picture
Reload stored events every 15 minutes (and after boot) so stats and rankings never lose data
4461572 verified
Raw History Blame Contribute Delete
4.34 kB
import pyarrow.parquet as pq
import pytest
from app.events import COLUMNS, ClientEvent, to_row
from app.sink import HubParquetSink, LocalParquetSink, rows_to_parquet_bytes
def rows(n):
return [to_row(ClientEvent(event_type="session", model_family="Qwen", quantization="4-bit")) for _ in range(n)]
def test_batch_becomes_one_shard(tmp_path):
s = LocalParquetSink(tmp_path, flush_seconds=999)
s.add(rows(7))
s.add(rows(5))
assert s.flush()
shards = list((tmp_path / "data/incoming").rglob("*.parquet"))
assert len(shards) == 1
t = pq.read_table(shards[0])
assert t.num_rows == 12 and t.column_names == list(COLUMNS)
assert s.flush() and len(list((tmp_path / "data/incoming").rglob("*.parquet"))) == 1 # empty flush = no shard
s.add(rows(1))
s.flush()
assert len(list((tmp_path / "data/incoming").rglob("*.parquet"))) == 2 # appends, never rewrites
assert len(s.read_existing()) == 13
class FlakyApi:
def __init__(self, fail_times):
self.fail_times = fail_times
self.commits = []
self.token = None
def create_commit(self, repo_id, repo_type, operations, commit_message):
if self.fail_times > 0:
self.fail_times -= 1
raise ConnectionError("hub down")
assert repo_type == "dataset"
self.commits.append([op.path_in_repo for op in operations])
def test_hub_failure_keeps_spool_and_retries(tmp_path):
api = FlakyApi(fail_times=2)
s = HubParquetSink("org/data", None, spool_dir=tmp_path, api=api, flush_seconds=999)
s.add(rows(3))
assert not s.flush() and s.pending == 3 and not s.status()["healthy"]
# a restart in between must not lose rows
s2 = HubParquetSink("org/data", None, spool_dir=tmp_path, api=api, flush_seconds=999)
assert s2.pending == 3
assert not s2.flush()
assert s2.flush() and s2.pending == 0 and s2.status()["healthy"]
assert len(api.commits) == 1 and len(api.commits[0]) == 1
assert api.commits[0][0].startswith("data/incoming/") and api.commits[0][0].endswith(".parquet")
s3 = HubParquetSink("org/data", None, spool_dir=tmp_path, api=api, flush_seconds=999)
assert s3.pending == 0
def test_local_refuses_overwrite(tmp_path):
s = LocalParquetSink(tmp_path, flush_seconds=999)
data = rows_to_parquet_bytes(rows(1))
s._write_shard("data/incoming/x.parquet", data)
with pytest.raises(FileExistsError):
s._write_shard("data/incoming/x.parquet", data)
def test_dataset_schema_is_deliberate():
"""Changing columns changes the public dataset schema: bump this list on purpose, and
migrate or document existing shards (see the dataset card's versioning section)."""
assert len(COLUMNS) == 67
assert {"perplexity", "perplexity_stderr", "eval_dataset", "eval_tokens"} <= set(COLUMNS)
def test_size_triggered_flush(tmp_path, monkeypatch):
import time
import app.sink as sink_mod
monkeypatch.setattr(sink_mod, "FLUSH_ROWS", 5)
s = LocalParquetSink(tmp_path, flush_seconds=999)
s.add(rows(3))
assert s.pending == 3
s.add(rows(3)) # crosses FLUSH_ROWS -> flushes in the background
for _ in range(50):
if s.pending == 0:
break
time.sleep(0.05)
assert s.pending == 0 and len(list((tmp_path / "data/incoming").rglob("*.parquet"))) == 1
def test_reads_monthly_and_incoming(tmp_path):
from app.sink import rows_to_parquet_bytes as rb
(tmp_path / "data/events").mkdir(parents=True)
(tmp_path / "data/events/2026-08.parquet").write_bytes(rb(rows(4)))
s = LocalParquetSink(tmp_path, flush_seconds=999)
s.add(rows(2))
s.flush()
assert len(s.read_existing()) == 6
def test_reload_neither_misses_nor_double_counts(tmp_path):
import time
s = LocalParquetSink(tmp_path, flush_seconds=999)
s.add(rows(3))
stored = s.read_existing()
assert len(stored) + len(s.live_rows()) == 3 # accepted, not yet written
s.flush()
assert len(s.read_existing()) + len(s.live_rows()) == 6 # written but not yet reloaded: still visible (overlap is fine before a reload)
started = time.time()
stored = s.read_existing()
s.forget_flushed_before(started)
s.add(rows(2))
assert len(stored) + len(s.live_rows()) == 5 # after reload: 3 stored + 2 new, no duplicates