Documentation
¶
Overview ¶
Package index 提供 local-hybrid 引擎的不可变索引持久化: staging 构建、checksum 校验、原子发布与 active/previous 回退。 任何 segment 目录发布后永不修改;发布只切换 active 指针。
Index ¶
- Constants
- Variables
- func ChecksumFile(path string) (string, error)
- func NewBuildID() string
- type Counts
- type FileEntry
- type Journal
- func (j *Journal) Append(vectors map[string][]float32) error
- func (j *Journal) Close() error
- func (j *Journal) CompactAfterPublish(published map[string]bool) error
- func (j *Journal) MarkRejected(hashes []string) error
- func (j *Journal) Rejected(hash string) bool
- func (j *Journal) RejectedCount() int
- func (j *Journal) Snapshot() map[string][]float32
- type Manifest
- type ProcessLock
- type SegmentRef
- type Store
- func (s *Store) ActiveRevision() (string, bool, error)
- func (s *Store) BeginStaging(buildID string) (string, error)
- func (s *Store) CleanupOrphanSegments() error
- func (s *Store) CleanupStaging() error
- func (s *Store) DiscardStaging(buildID string) error
- func (s *Store) JournalDir() string
- func (s *Store) ListRevisions() ([]string, error)
- func (s *Store) LoadManifest(revision string) (*Manifest, error)
- func (s *Store) LockPath() string
- func (s *Store) Publish(manifest *Manifest, stagingPath string) error
- func (s *Store) RemoveRevision(revision string) error
- func (s *Store) ResolveUsable() (*Manifest, []string, error)
- func (s *Store) Root() string
- func (s *Store) SegmentPath(manifest *Manifest) string
- func (s *Store) SegmentPathFor(segmentID string) string
- func (s *Store) VerifyManifest(manifest *Manifest) error
- type WorkspaceIdentity
Constants ¶
const ( ManifestSchemaV1 = 1 ManifestSchemaV2 = 2 )
manifest schema 版本:
- v1(Stage 2/3):单 segment,字段在 Manifest 顶层。
- v2(Stage 4,D1):多 segment + tombstone,支持增量 delta 与 跨 revision segment 共享;v1 在读取时归一为单段 v2 视图。
const ChunksFileName = "chunks.jsonl"
ChunksFileName 是 segment 内 chunk 数据文件名(JSONL,每行一个 chunk)。
const LexicalDirName = "lexical.bleve"
LexicalDirName 是 segment 内 Bleve 索引目录名。
const ManifestSchemaVersion = ManifestSchemaV2
ManifestSchemaVersion 是当前构建路径写出的版本(P4-T03 起为 v2; L12:常量此前滞留 V1 与事实脱节,仅测试引用,现对齐)。
const MaxRevisionChain = 16
MaxRevisionChain 是 previous 链遍历的深度上限(review S3):正常保留 链长 ≤2(active+previous),上限只在链被外部损坏/成环时兜底。
Variables ¶
var ErrLockHeld = errors.New("索引写锁被其他进程持有")
ErrLockHeld 表示锁被其他存活进程持有。
var ErrLockLost = errors.New("索引写锁已被其他进程接管")
ErrLockLost 表示锁已被接管(持有者必须中止写入)。
var ErrNoUsableRevision = errors.New("没有可用的索引 revision")
ErrNoUsableRevision 表示 active 与 previous 均不可用。
Functions ¶
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 ¶
OpenJournal 打开(必要时创建)store 的 journal,载入既有条目与拒绝集。 维度不符的历史条目整体丢弃(profile 子树隔离下不应出现,防御路径)。
func (*Journal) CompactAfterPublish ¶
CompactAfterPublish 清除已随 revision 入盘的条目(K41:发布即 GC), 并压实文件。
func (*Journal) MarkRejected ¶
MarkRejected 持久化记录零向量/NaN 内容 hash。
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 ¶
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 ¶
SemanticComplete 报告语义覆盖是否完整(空仓库按完整计)。
func (*Manifest) TombstoneSet ¶
TombstoneSet 返回 tombstone 查找集。
type ProcessLock ¶
type ProcessLock struct {
// contains filtered or unexported fields
}
ProcessLock 是 profile 子树的跨进程写独占锁。
func AcquireLock ¶
func AcquireLock(store *Store) (*ProcessLock, error)
AcquireLock 获取 store 的写锁;被存活进程持有时返回 ErrLockHeld。
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 ¶
OpenExistingStore 以既有子树根目录打开 Store(bench 跨子树向量复用工具 面;不创建目录,根不存在或缺 manifests 结构即报错——防误指新建空树)。
func (*Store) ActiveRevision ¶
ActiveRevision 读取 active 指针;不存在时返回 ok=false。
func (*Store) BeginStaging ¶
BeginStaging 创建并返回一次构建的 staging 目录。
func (*Store) CleanupOrphanSegments ¶
CleanupOrphanSegments 删除不被任何 manifest 引用的 segment 目录 (review S5:Publish 在 rename 之后中断会留下孤儿 segment; v2 起同时兜底 RemoveRevision 中断残留,暗坑 K42)。 与 CleanupStaging 同时机(store 创建时)调用。
func (*Store) CleanupStaging ¶
CleanupStaging 清空全部残留 staging(启动时调用;暗坑 K16)。 active/previous revision 不受影响。
func (*Store) DiscardStaging ¶
DiscardStaging 删除一次构建的 staging 目录(取消/失败路径)。
func (*Store) ListRevisions ¶
ListRevisions 返回全部持久化 manifest 的 revision 标识(无序)。
func (*Store) LoadManifest ¶
LoadManifest 读取、校验并归一化指定 revision 的 manifest (v1 归一为单段 v2 视图,D1)。
func (*Store) Publish ¶
Publish 原子发布一次构建:
- staging 目录整体改名为 segments/<最新 segment>(同卷 rename); stagingPath 为空表示 manifest-only 发布(如仅删除的 delta,D1), 跳过本步;
- 写入 manifests/<revision>.json(temp+rename);
- 更新 active.json 指针(temp+Sync+rename+父目录 fsync)。
任一步骤中断都不影响当前 active revision 的可用性。
func (*Store) RemoveRevision ¶
RemoveRevision 删除一个 revision 的 manifest,并回收仅被其引用的 segment。调用方必须保证该 revision 不是 active/previous 且无打开句柄。 v2 起 segment 可被多个 revision 共享(delta 链,D1),删除顺序为 manifest 先(消除引用)、无引用 segment 后:中断残留的孤儿 segment 由启动清理回收(暗坑 K42)。
func (*Store) ResolveUsable ¶
ResolveUsable 返回首个通过校验的 revision:active 优先,损坏时沿 previous 链回退(暗坑 K1/K2 的恢复路径)。回退发生时返回的 degradedFrom 记录被跳过的损坏 revision,供状态上报。链遍历带环检测与深度上限 (review S3:被外部编辑成环的 manifest 不得挂起 daemon)。
func (*Store) SegmentPath ¶
SegmentPath 返回 manifest 最新 segment 的目录(v1 语义下即唯一 segment)。
func (*Store) SegmentPathFor ¶
SegmentPathFor 返回指定 segment 的目录。
func (*Store) VerifyManifest ¶
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 是被索引工作区的规范身份。