Files
xinmi/internal/application/service/knowledge_process_embedding_failure_test.go
yawan f7fc992f57
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
2026-09-22 16:19:06 +08:00

92 lines
3.2 KiB
Go

package service
import (
"context"
"errors"
"testing"
"github.com/Tencent/WeKnora/internal/models/embedding"
"github.com/Tencent/WeKnora/internal/types"
"github.com/Tencent/WeKnora/internal/types/interfaces"
"github.com/stretchr/testify/require"
)
// embeddingInitFailureRepo captures the update made by processChunks. The
// real repository has the same UpdateKnowledge contract; this small fake keeps
// the test focused on the terminal state transition.
type embeddingInitFailureRepo struct {
interfaces.KnowledgeRepository
knowledge *types.Knowledge
updated int
}
func (r *embeddingInitFailureRepo) GetKnowledgeByID(context.Context, uint64, string) (*types.Knowledge, error) {
return r.knowledge, nil
}
func (r *embeddingInitFailureRepo) UpdateKnowledge(_ context.Context, knowledge *types.Knowledge) error {
r.updated++
r.knowledge = knowledge
return nil
}
type embeddingInitFailureModelService struct {
interfaces.ModelService
err error
}
func (s embeddingInitFailureModelService) GetEmbeddingModel(context.Context, string) (embedding.Embedder, error) {
return nil, s.err
}
// TestProcessChunks_EmbeddingModelFailurePersistsFailedState guards the
// failure path that previously just returned from processChunks. A provider
// configuration error must be visible to callers and the persisted stage
// trace; otherwise the knowledge row remains "processing" indefinitely.
func TestProcessChunks_EmbeddingModelFailurePersistsFailedState(t *testing.T) {
knowledge := &types.Knowledge{
ID: "knowledge-embedding-failure",
TenantID: 1,
KnowledgeBaseID: "kb-1",
ParseStatus: types.ParseStatusProcessing,
}
repo := &embeddingInitFailureRepo{knowledge: knowledge}
failure := errors.New("embedding provider credentials are invalid")
// Use the real span tracker against the test SQLite schema so this also
// proves the embedding stage is failed rather than left running.
tracker, db := setupSpanTrackerTest(t)
_, attempt, err := tracker.OpenAttempt(context.Background(), knowledge.ID, "trace")
require.NoError(t, err)
tenant := &types.Tenant{ID: 1}
ctx := context.WithValue(context.Background(), types.TenantInfoContextKey, tenant)
ctx = withAttempt(ctx, attempt)
svc := &knowledgeService{
repo: repo,
modelService: embeddingInitFailureModelService{err: failure},
spanTracker: tracker,
}
kb := &types.KnowledgeBase{
ID: "kb-1",
EmbeddingModelID: "missing-model",
IndexingStrategy: types.IndexingStrategy{VectorEnabled: true},
}
svc.processChunks(ctx, kb, knowledge, nil)
require.Equal(t, 1, repo.updated, "failure must be persisted immediately")
require.Equal(t, types.ParseStatusFailed, knowledge.ParseStatus)
require.Equal(t, failure.Error(), knowledge.ErrorMessage)
require.False(t, knowledge.UpdatedAt.IsZero())
var row struct{ Status, ErrorCode, ErrorMessage string }
require.NoError(t, db.Table("knowledge_processing_spans").
Select("status, error_code, error_message").
Where("knowledge_id = ? AND attempt = ? AND name = ?", knowledge.ID, attempt, types.StageEmbedding).
First(&row).Error)
require.Equal(t, types.SpanStatusFailed, row.Status)
require.Equal(t, "EMBEDDING_PROVIDER_FAIL", row.ErrorCode)
require.Contains(t, row.ErrorMessage, "get embedding model failed")
}