Ctrl K
ComunidadGuías…

test-int/test_indexed_bytes_work_units.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""Indexing reports the stored bytes it actually indexed, for work-unit billing.

Cloud bills per-tenant work units from these counts, so a file the checker finds
current must report zero: only content the indexer read and parsed counts.
"""

import pytest

from basic_memory.file_utils import compute_checksum
from basic_memory.index.local_project import LocalProjectIndexRuntimeFactory
from basic_memory.indexing.models import IndexFileJobStatus
from basic_memory.models import Project
from basic_memory.runtime.jobs import RuntimeIndexFileBatchJobRequest, RuntimeObservedIndexFile
from basic_memory.runtime.projects import ProjectRuntimeReference

# Complete frontmatter, so indexing never rewrites the file and the stored bytes
# stay exactly what the test wrote.
NOTE_CONTENT = """---
title: Billing Note
type: note
permalink: notes/billing-note
---

# Billing Note

Unicode counts as bytes, not characters: café, naïve, 漢字.

- [fact] Work units bill on bytes indexed
"""


@pytest.mark.asyncio
async def test_batch_index_reports_bytes_indexed_and_zero_for_current_file(
    test_project: Project,
    project_config,
) -> None:
    path = "notes/billing-note.md"
    (project_config.home / "notes").mkdir(parents=True, exist_ok=True)
    # newline="\n" keeps the file's bytes equal to NOTE_CONTENT on Windows too
    (project_config.home / path).write_text(NOTE_CONTENT, encoding="utf-8", newline="\n")
    expected_bytes = len(NOTE_CONTENT.encode("utf-8"))
    runtime = await LocalProjectIndexRuntimeFactory().runtime_for_project(test_project)
    # The observed checksum lets the checker compare against the index and
    # decide the second pass is current without reading content.
    request = RuntimeIndexFileBatchJobRequest(
        project=ProjectRuntimeReference.from_project(test_project),
        batch_index=0,
        batch_count=1,
        observed_files=(
            RuntimeObservedIndexFile(
                path=path,
                checksum=await compute_checksum(NOTE_CONTENT),
                size=expected_bytes,
            ),
        ),
    )

    first = await runtime.batch_enqueuer.enqueue_index_file_batch(request)
    second = await runtime.batch_enqueuer.enqueue_index_file_batch(request)
    # The local enqueuer runs batches inline, so both calls return results.
    assert first is not None
    assert second is not None

    assert (project_config.home / path).read_text(encoding="utf-8") == NOTE_CONTENT
    assert first.file_results[0].status == IndexFileJobStatus.processed
    assert first.file_results[0].indexed_bytes == expected_bytes
    assert first.indexed_bytes == expected_bytes
    assert second.file_results[0].status == IndexFileJobStatus.current
    assert second.file_results[0].indexed_bytes == 0
    assert second.indexed_bytes == 0


@pytest.mark.asyncio
async def test_single_file_index_reports_bytes_indexed(
    test_project: Project,
    project_config,
) -> None:
    path = "notes/billing-note.md"
    (project_config.home / "notes").mkdir(parents=True, exist_ok=True)
    (project_config.home / path).write_text(NOTE_CONTENT, encoding="utf-8", newline="\n")
    dependencies = await LocalProjectIndexRuntimeFactory().dependencies_for_project(test_project)

    result = await dependencies.file_indexer.index_file(path, source="index")

    assert result.indexed_bytes == len(NOTE_CONTENT.encode("utf-8"))