dcdc8d1ddd
全栈知识治理平台首次入库(P1-P10 + 发布链路模拟验证闭环): - 治理核心:源目录/变更集/人工审核/发布批次/发布执行(fail-closed 闸口) - 测试通道:WeKnora 测试 KB 上传/轮询/验收;poll 完成时写入 parser_generation/index_generation,修复 manual/seed 路径发布闸口永久拦截 - 发布适配器 v071(本地 source=测试角色 / 云端 target=生产角色 模拟验证通过): * ES 导出/导入 mapping 自适应(.keyword 子字段、可选 tenant_id) * OSS locator 支持嵌套 scheme;chunks.seq_id 由目标序列分配 * bundle 归档同身份重试原子替换;verifier 按 bundle chunk_type 计数 * 回滚 job payload 支持 prior_execution_id(strict 解码) - 三通道发布+回滚演练实测:publish 4/4 verified,检索命中, rollback 4/4 rolled_back,目标端 PG is_enabled=false、ES is_enabled=false - 前端 A·Data-console 风格全站统一,120 用例通过 - 门禁:go vet / go test 全包通过,gofmt 干净
174 lines
5.0 KiB
Go
174 lines
5.0 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
ppconnector "knowledge-governance/internal/connectors/pp"
|
|
)
|
|
|
|
type LegacyImportReport struct {
|
|
Connections int
|
|
SourceItems int
|
|
ContentObjects int
|
|
Versions int
|
|
Publications int
|
|
}
|
|
|
|
func LoadPPCurrentItems(ctx context.Context, pool *pgxpool.Pool, connectionID string) (map[string]ppconnector.CurrentItem, error) {
|
|
rows, err := pool.Query(ctx, `
|
|
SELECT stable_external_id, revision
|
|
FROM source_items
|
|
WHERE source_connection_id = $1
|
|
ORDER BY stable_external_id`, connectionID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query current PP items: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
items := make(map[string]ppconnector.CurrentItem)
|
|
for rows.Next() {
|
|
var sourceHash string
|
|
var item ppconnector.CurrentItem
|
|
if err := rows.Scan(&sourceHash, &item.Revision); err != nil {
|
|
return nil, fmt.Errorf("scan current PP item: %w", err)
|
|
}
|
|
items[sourceHash] = item
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("iterate current PP items: %w", err)
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
func ImportPPLegacy(ctx context.Context, pool *pgxpool.Pool, plan ppconnector.ImportPlan) (LegacyImportReport, error) {
|
|
tx, err := pool.Begin(ctx)
|
|
if err != nil {
|
|
return LegacyImportReport{}, fmt.Errorf("begin PP legacy import: %w", err)
|
|
}
|
|
defer func() { _ = tx.Rollback(ctx) }()
|
|
|
|
report := LegacyImportReport{}
|
|
tag, err := tx.Exec(ctx, `INSERT INTO source_connections (
|
|
id, source_type, name, base_url, secret_ref, enabled, schedule, last_health
|
|
) VALUES ($1, $2, $3, $4, $5, $6, '{}'::jsonb, '{}'::jsonb)
|
|
ON CONFLICT DO NOTHING`,
|
|
plan.Connection.ID,
|
|
plan.Connection.Type,
|
|
plan.Connection.Name,
|
|
plan.Connection.BaseURL,
|
|
plan.Connection.SecretRef,
|
|
plan.Connection.Enabled,
|
|
)
|
|
if err != nil {
|
|
return LegacyImportReport{}, fmt.Errorf("insert PP source connection: %w", err)
|
|
}
|
|
report.Connections = int(tag.RowsAffected())
|
|
|
|
for _, content := range plan.ContentObjects {
|
|
tag, err = tx.Exec(ctx, `INSERT INTO content_objects (
|
|
id, sha256, size_bytes, mime, validated_format, local_spool_ref, content_state
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
ON CONFLICT DO NOTHING`,
|
|
content.ID,
|
|
content.SHA256,
|
|
content.SizeBytes,
|
|
content.MIME,
|
|
content.ValidatedFormat,
|
|
content.LocalSpoolRef,
|
|
content.State,
|
|
)
|
|
if err != nil {
|
|
return LegacyImportReport{}, fmt.Errorf("insert PP content object: %w", err)
|
|
}
|
|
report.ContentObjects += int(tag.RowsAffected())
|
|
}
|
|
|
|
for _, item := range plan.SourceItems {
|
|
tag, err = tx.Exec(ctx, `INSERT INTO source_items (
|
|
id, source_connection_id, stable_external_id, canonical_uri_hash,
|
|
parent_external_id, normalized_path, title, item_type, size_bytes,
|
|
mime, revision, visibility, visibility_origin, last_seen_scan_id,
|
|
source_change, absence_streak, identity_confidence
|
|
) VALUES (
|
|
$1, $2, $3, $4, $5, $6, $7, $8, $9,
|
|
$10, $11, $12, $13, $14, $15, $16, 'stable_id'
|
|
)
|
|
ON CONFLICT DO NOTHING`,
|
|
item.ID,
|
|
item.SourceConnectionID,
|
|
item.StableExternalID,
|
|
item.CanonicalURIHash,
|
|
item.ParentExternalID,
|
|
item.NormalizedPath,
|
|
item.Title,
|
|
item.ItemType,
|
|
item.SizeBytes,
|
|
item.MIME,
|
|
item.Revision,
|
|
item.Visibility,
|
|
item.VisibilityOrigin,
|
|
item.LastSeenScanID,
|
|
item.SourceChange,
|
|
item.AbsenceStreak,
|
|
)
|
|
if err != nil {
|
|
return LegacyImportReport{}, fmt.Errorf("insert PP source item: %w", err)
|
|
}
|
|
report.SourceItems += int(tag.RowsAffected())
|
|
}
|
|
|
|
for _, version := range plan.Versions {
|
|
tag, err = tx.Exec(ctx, `INSERT INTO source_item_versions (
|
|
id, source_item_id, revision, content_object_id, content_state,
|
|
download_error, raw_record_summary, source_updated_at
|
|
) VALUES ($1, $2, $3, $4, $5, $6, CAST($7 AS JSONB), $8)
|
|
ON CONFLICT DO NOTHING`,
|
|
version.ID,
|
|
version.SourceItemID,
|
|
version.Revision,
|
|
version.ContentObjectID,
|
|
version.ContentState,
|
|
version.DownloadError,
|
|
string(version.RawRecordSummary),
|
|
version.SourceUpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return LegacyImportReport{}, fmt.Errorf("insert PP source item version: %w", err)
|
|
}
|
|
report.Versions += int(tag.RowsAffected())
|
|
}
|
|
|
|
for _, publication := range plan.Publications {
|
|
tag, err = tx.Exec(ctx, `INSERT INTO test_publications (
|
|
id, source_item_version_id, test_kb_id, knowledge_id,
|
|
ingest_state, processing_state, retrieval_state,
|
|
parser_generation, index_generation, last_error, retry_count
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
ON CONFLICT DO NOTHING`,
|
|
publication.ID,
|
|
publication.SourceItemVersionID,
|
|
publication.TestKBID,
|
|
publication.KnowledgeID,
|
|
publication.IngestState,
|
|
publication.ProcessingState,
|
|
publication.RetrievalState,
|
|
publication.ParserGeneration,
|
|
publication.IndexGeneration,
|
|
publication.LastError,
|
|
publication.RetryCount,
|
|
)
|
|
if err != nil {
|
|
return LegacyImportReport{}, fmt.Errorf("insert PP test publication: %w", err)
|
|
}
|
|
report.Publications += int(tag.RowsAffected())
|
|
}
|
|
|
|
if err := tx.Commit(ctx); err != nil {
|
|
return LegacyImportReport{}, fmt.Errorf("commit PP legacy import: %w", err)
|
|
}
|
|
return report, nil
|
|
}
|