index

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package index 提供 local-hybrid 引擎的不可变索引持久化: staging 构建、checksum 校验、原子发布与 active/previous 回退。 任何 segment 目录发布后永不修改;发布只切换 active 指针。

Index

Constants

View Source
const (
	ManifestSchemaV1 = 1
	ManifestSchemaV2 = 2
)

manifest schema 版本:

  • v1(Stage 2/3):单 segment,字段在 Manifest 顶层。
  • v2(Stage 4,D1):多 segment + tombstone,支持增量 delta 与 跨 revision segment 共享;v1 在读取时归一为单段 v2 视图。
View Source
const ChunksFileName = "chunks.jsonl"

ChunksFileName 是 segment 内 chunk 数据文件名(JSONL,每行一个 chunk)。

View Source
const LexicalDirName = "lexical.bleve"

LexicalDirName 是 segment 内 Bleve 索引目录名。

View Source
const ManifestSchemaVersion = ManifestSchemaV2

ManifestSchemaVersion 是当前构建路径写出的版本(P4-T03 起为 v2; L12:常量此前滞留 V1 与事实脱节,仅测试引用,现对齐)。

View Source
const MaxRevisionChain = 16

MaxRevisionChain 是 previous 链遍历的深度上限(review S3):正常保留 链长 ≤2(active+previous),上限只在链被外部损坏/成环时兜底。

Variables

View Source
var ErrLockHeld = errors.New("索引写锁被其他进程持有")

ErrLockHeld 表示锁被其他存活进程持有。

View Source
var ErrLockLost = errors.New("索引写锁已被其他进程接管")

ErrLockLost 表示锁已被接管(持有者必须中止写入)。

View Source
var ErrNoUsableRevision = errors.New("没有可用的索引 revision")

ErrNoUsableRevision 表示 active 与 previous 均不可用。

Functions

func ChecksumFile

func ChecksumFile(path string) (string, error)

ChecksumFile 计算文件 sha256 hex。

func NewBuildID

func NewBuildID() string

NewBuildID 生成一次构建的随机标识(同时用作 segment ID 与 revision 后缀)。

Types

type Counts

type Counts struct {
	Files  int   `json:"files"`
	Chunks int   `json:"chunks"`
	Bytes  int64 `json:"bytes"`
}

Counts 汇总本 revision 的规模。

type FileEntry

type FileEntry struct {
	ContentHash string `json:"content_hash"`
	ChunkCount  int    `json:"chunk_count"`
	// SegmentID 标识当前版本 chunk 所在 segment(v2;v1 归一时填充)。
	SegmentID string `json:"segment_id,omitempty"`
	// Bytes 是该文件已索引 chunk 内容字节数(v2;S20 口径基础——
	// Counts.Bytes = Σ 存活 FileEntry.Bytes;v1 归一后为 0,compaction
	// 全量重建时补齐)。
	Bytes int64 `json:"bytes,omitempty"`
	// CoveredChunks 是该文件有向量的 chunk 数(v2;delta 构建的覆盖
	// 口径基础,暗坑 K31/K51:VectorCount = Σ 存活 CoveredChunks)。
	CoveredChunks int `json:"covered_chunks,omitempty"`
}

FileEntry 记录单个文件在本 revision 中的内容身份。 注记(Stage 2 review S17):ContentHash 写入的是 workspace 扫描的 blobName = sha256(relpath + content),含相对路径成分——用于文件级 变更判定足够;embedding 复用键控使用 chunk 级纯内容 hash,与本字段 无关。字段名保留以维持 v1 兼容,语义以本注记为准。

type Journal

type Journal struct {
	// contains filtered or unexported fields
}

Journal 是 per-profile 的 embedding 断点续嵌暂存区(阶段计划 D4): 每批嵌入成功即 append 落盘,构建被取消/超时/kill 后已付费向量不丢失; revision 发布后清除已入盘条目。它不是长期缓存——向量事实源始终是 revision(暗坑 K41),journal 只在"已付费未发布"窗口存在且有界。

vectors.journal 记录格式(小端):

uint32 payloadLen | payload | uint32 crc32(payload)
payload = uint16 hashLen | hash | uint32 dim | dim × float32

尾部半写记录在打开时截断(暗坑 K40)。文件只存 hash 与向量, 不存 chunk 明文(暗坑 K54)。

func OpenJournal

func OpenJournal(store *Store, dimension int) (*Journal, error)

OpenJournal 打开(必要时创建)store 的 journal,载入既有条目与拒绝集。 维度不符的历史条目整体丢弃(profile 子树隔离下不应出现,防御路径)。

func (*Journal) Append

func (j *Journal) Append(vectors map[string][]float32) error

Append 落盘一批已付费向量(批成功即调用,D4);每批一次 fsync。

func (*Journal) Close

func (j *Journal) Close() error

Close 关闭 journal 文件句柄。

func (*Journal) CompactAfterPublish

func (j *Journal) CompactAfterPublish(published map[string]bool) error

CompactAfterPublish 清除已随 revision 入盘的条目(K41:发布即 GC), 并压实文件。

func (*Journal) MarkRejected

func (j *Journal) MarkRejected(hashes []string) error

MarkRejected 持久化记录零向量/NaN 内容 hash。

func (*Journal) Rejected

func (j *Journal) Rejected(hash string) bool

Rejected 报告 hash 是否在持久化拒绝集(K35 修订,跨重启生效)。

func (*Journal) RejectedCount

func (j *Journal) RejectedCount() int

RejectedCount 返回拒绝集规模(状态上报)。

func (*Journal) Snapshot

func (j *Journal) Snapshot() map[string][]float32

Snapshot 返回当前条目视图(复用源;调用方不得修改向量)。

type Manifest

type Manifest struct {
	SchemaVersion    int               `json:"schema_version"`
	Workspace        WorkspaceIdentity `json:"workspace"`
	EngineID         string            `json:"engine_id"`
	EngineVersion    string            `json:"engine_version"`
	Revision         string            `json:"revision"`
	PreviousRevision string            `json:"previous_revision,omitempty"`
	PolicyHash       string            `json:"policy_hash,omitempty"`
	ChunkerID        string            `json:"chunker_id"`
	ChunkerVersion   string            `json:"chunker_version"`
	// ChunkerCapabilities 记录每语言实际使用的切分能力(ast|fallback),
	// 禁止把 fallback 上报为 ast。
	ChunkerCapabilities map[string]string    `json:"chunker_capabilities,omitempty"`
	LexicalEngine       string               `json:"lexical_engine"`
	LexicalVersion      string               `json:"lexical_version"`
	SegmentID           string               `json:"segment_id"`
	Files               map[string]FileEntry `json:"files"`
	Counts              Counts               `json:"counts"`
	// ChunksChecksum 是 segment 内 chunks.jsonl 的 sha256,
	// 打开 revision 前校验,失败即回退 previous。
	ChunksChecksum string    `json:"chunks_checksum"`
	CreatedAt      time.Time `json:"created_at"`
	ActivatedAt    time.Time `json:"activated_at"`

	// EmbeddingProvider/Model/Dimension/Dtype 记录向量身份;与 profile
	// 子树对应,禁止混用(暗坑 K24)。不含任何凭据(暗坑 K21)。
	EmbeddingProvider  string `json:"embedding_provider,omitempty"`
	EmbeddingModel     string `json:"embedding_model,omitempty"`
	EmbeddingDimension int    `json:"embedding_dimension,omitempty"`
	EmbeddingDtype     string `json:"embedding_dtype,omitempty"`
	// EmbeddingProfileHash 与索引目录 profile 段一致(阶段计划 D4)。
	EmbeddingProfileHash string `json:"embedding_profile_hash,omitempty"`
	// VectorsChecksum/VectorsIndexChecksum 校验 vectors.dat/vectors.idx;
	// 校验失败仅语义路降级,不废整个 revision(暗坑 K25)。
	VectorsChecksum      string `json:"vectors_checksum,omitempty"`
	VectorsIndexChecksum string `json:"vectors_index_checksum,omitempty"`
	// VectorCount 是已覆盖 chunk 行数;semantic coverage = VectorCount /
	// Counts.Chunks(暗坑 K31,读取时计算不落盘防口径漂移)。
	// v2 语义:存活(newest-wins)chunk 中有向量者的计数。
	VectorCount int `json:"vector_count,omitempty"`

	// Segments 是本 revision 引用的全部 segment(优先级升序,最新在后);
	// delta 链下 segment 可被多个 revision 共享,删除必须引用计数。
	Segments []SegmentRef `json:"segments,omitempty"`
	// Tombstones 是相对 segment 联合视图被删除/改名的 relpath(排序);
	// 查询期在召回后统一过滤(暗坑 K39)。
	Tombstones []string `json:"tombstones,omitempty"`
}

Manifest 描述一个不可变索引 revision。字段一经写入不再变更。

func (*Manifest) HasVectors

func (m *Manifest) HasVectors() bool

HasVectors 报告本 revision 是否携带向量数据文件(任一 segment 有即有)。

func (*Manifest) NewestSegment

func (m *Manifest) NewestSegment() SegmentRef

NewestSegment 返回优先级最高(最新)的 segment 引用; 未 Normalize 的 v1 manifest 走 legacy 字段合成(防御路径)。

func (*Manifest) Normalize

func (m *Manifest) Normalize()

Normalize 把 v1 单段 manifest 归一为 v2 视图(幂等):合成 Segments 并为 Files 填充 SegmentID。v2 manifest 原样返回。

func (*Manifest) SemanticComplete

func (m *Manifest) SemanticComplete() bool

SemanticComplete 报告语义覆盖是否完整(空仓库按完整计)。

func (*Manifest) TombstoneSet

func (m *Manifest) TombstoneSet() map[string]bool

TombstoneSet 返回 tombstone 查找集。

func (*Manifest) Validate

func (m *Manifest) Validate() error

Validate 检查 manifest 自身的结构完整性(按版本分支;未知版本显式 拒绝——旧二进制读到未来格式必须报错而非静默错读,暗坑 K43)。

type ProcessLock

type ProcessLock struct {
	// contains filtered or unexported fields
}

ProcessLock 是 profile 子树的跨进程写独占锁。

func AcquireLock

func AcquireLock(store *Store) (*ProcessLock, error)

AcquireLock 获取 store 的写锁;被存活进程持有时返回 ErrLockHeld。

func (*ProcessLock) Release

func (l *ProcessLock) Release()

Release 停止心跳并删除锁文件(仍持有时);幂等。

func (*ProcessLock) Verify

func (l *ProcessLock) Verify() error

Verify 复验锁仍归自己持有;写路径关键点调用(K46)。

type SegmentRef

type SegmentRef struct {
	ID             string `json:"id"`
	ChunksChecksum string `json:"chunks_checksum"`
	// ChunksIndexChecksum 校验 chunks.idx 偏移索引(P4-T08 填充)。
	ChunksIndexChecksum  string `json:"chunks_index_checksum,omitempty"`
	VectorsChecksum      string `json:"vectors_checksum,omitempty"`
	VectorsIndexChecksum string `json:"vectors_index_checksum,omitempty"`
	Counts               Counts `json:"counts"`
	VectorCount          int    `json:"vector_count,omitempty"`
}

SegmentRef 描述 revision 引用的一个不可变 segment(v2 起)。 列表序为优先级升序:基段在前、最新 delta 在后(newest-wins)。

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store 管理单个 <workspace, profile> 的索引持久化目录。 daemon 内同一 Store 的 Publish 由上层 singleflight 串行化。

func NewStore

func NewStore(cacheDir string, namespace string, workspaceKey string, profileKey string) (*Store, error)

NewStore 定位(必要时创建)索引根目录: <cacheDir>/<namespace>/engines/local-hybrid/<workspaceKey>/<profileKey>/

func OpenExistingStore

func OpenExistingStore(root string) (*Store, error)

OpenExistingStore 以既有子树根目录打开 Store(bench 跨子树向量复用工具 面;不创建目录,根不存在或缺 manifests 结构即报错——防误指新建空树)。

func (*Store) ActiveRevision

func (s *Store) ActiveRevision() (string, bool, error)

ActiveRevision 读取 active 指针;不存在时返回 ok=false。

func (*Store) BeginStaging

func (s *Store) BeginStaging(buildID string) (string, error)

BeginStaging 创建并返回一次构建的 staging 目录。

func (*Store) CleanupOrphanSegments

func (s *Store) CleanupOrphanSegments() error

CleanupOrphanSegments 删除不被任何 manifest 引用的 segment 目录 (review S5:Publish 在 rename 之后中断会留下孤儿 segment; v2 起同时兜底 RemoveRevision 中断残留,暗坑 K42)。 与 CleanupStaging 同时机(store 创建时)调用。

func (*Store) CleanupStaging

func (s *Store) CleanupStaging() error

CleanupStaging 清空全部残留 staging(启动时调用;暗坑 K16)。 active/previous revision 不受影响。

func (*Store) DiscardStaging

func (s *Store) DiscardStaging(buildID string) error

DiscardStaging 删除一次构建的 staging 目录(取消/失败路径)。

func (*Store) JournalDir

func (s *Store) JournalDir() string

JournalDir 返回 store 的 journal 目录。

func (*Store) ListRevisions

func (s *Store) ListRevisions() ([]string, error)

ListRevisions 返回全部持久化 manifest 的 revision 标识(无序)。

func (*Store) LoadManifest

func (s *Store) LoadManifest(revision string) (*Manifest, error)

LoadManifest 读取、校验并归一化指定 revision 的 manifest (v1 归一为单段 v2 视图,D1)。

func (*Store) LockPath

func (s *Store) LockPath() string

LockPath 返回 store 的锁文件路径。

func (*Store) Publish

func (s *Store) Publish(manifest *Manifest, stagingPath string) error

Publish 原子发布一次构建:

  1. staging 目录整体改名为 segments/<最新 segment>(同卷 rename); stagingPath 为空表示 manifest-only 发布(如仅删除的 delta,D1), 跳过本步;
  2. 写入 manifests/<revision>.json(temp+rename);
  3. 更新 active.json 指针(temp+Sync+rename+父目录 fsync)。

任一步骤中断都不影响当前 active revision 的可用性。

func (*Store) RemoveRevision

func (s *Store) RemoveRevision(revision string) error

RemoveRevision 删除一个 revision 的 manifest,并回收仅被其引用的 segment。调用方必须保证该 revision 不是 active/previous 且无打开句柄。 v2 起 segment 可被多个 revision 共享(delta 链,D1),删除顺序为 manifest 先(消除引用)、无引用 segment 后:中断残留的孤儿 segment 由启动清理回收(暗坑 K42)。

func (*Store) ResolveUsable

func (s *Store) ResolveUsable() (*Manifest, []string, error)

ResolveUsable 返回首个通过校验的 revision:active 优先,损坏时沿 previous 链回退(暗坑 K1/K2 的恢复路径)。回退发生时返回的 degradedFrom 记录被跳过的损坏 revision,供状态上报。链遍历带环检测与深度上限 (review S3:被外部编辑成环的 manifest 不得挂起 daemon)。

func (*Store) Root

func (s *Store) Root() string

Root 返回该 Store 的根目录(供状态上报)。

func (*Store) SegmentPath

func (s *Store) SegmentPath(manifest *Manifest) string

SegmentPath 返回 manifest 最新 segment 的目录(v1 语义下即唯一 segment)。

func (*Store) SegmentPathFor

func (s *Store) SegmentPathFor(segmentID string) string

SegmentPathFor 返回指定 segment 的目录。

func (*Store) VerifyManifest

func (s *Store) VerifyManifest(manifest *Manifest) error

VerifyManifest 校验 revision 数据完整性:逐 segment 的 chunks checksum 与 lexical 目录存在性。Bleve 索引自身的深度校验由打开动作完成 (打开失败视为损坏)。

type WorkspaceIdentity

type WorkspaceIdentity struct {
	CanonicalPath string `json:"canonical_path"`
	PathKind      string `json:"path_kind,omitempty"`
	HostOS        string `json:"host_os,omitempty"`
}

WorkspaceIdentity 是被索引工作区的规范身份。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL