Files
knowledge-governance/internal/platform/postgres/artifact_fetch_store.go
T
姚章浩 b3c9331966 feat(ingest): 源与目录文件名过滤及钉钉文档导出
- filename_filter_rules table (000035) with source-root and per-directory rows
- additive inheritance: source default + every ancestor directory contributes
- filename_is_filtered() SQL predicate applied to catalog browsing, subtree
  counts, change-set diffing, routing fan-out and artifact fetch manifests
- fetch_state 'filtered' (CHECK extended); reconcile cancels/restores fetch
  jobs, retires planned publications and blocks items when rules change
- GET/PUT/DELETE /api/v1/filename-filters (Idempotency-Key, normalized
  extensions) + Settings and Catalog filter editors
- failJobSQL no longer swallows the claimed row when the failure projection
  upserts (fixes spurious 'lease lost' retries)
- DingTalk live fetch: adoc/axls now use the export-job pipeline (HTTP 403
  from file/download fixed), header-signature downloads supported
2026-09-30 10:54:07 +08:00

51 lines
2.0 KiB
Go

package postgres
import (
"context"
"errors"
"fmt"
"github.com/jackc/pgx/v5"
"knowledge-governance/internal/workflows/artifactfetch"
)
// LoadArtifactFetchManifest resolves one pending intent plus its live source
// coordinates for the fetch script, keyed by the connection-stable node id.
func (s *Store) LoadArtifactFetchManifest(ctx context.Context, connectionID, nodeID string) (artifactfetch.Manifest, error) {
return loadArtifactFetchManifest(ctx, s.db, connectionID, nodeID)
}
func loadArtifactFetchManifest(ctx context.Context, db interface {
QueryRow(context.Context, string, ...any) pgx.Row
}, connectionID, nodeID string) (artifactfetch.Manifest, error) {
var manifest artifactfetch.Manifest
var fetchState string
err := db.QueryRow(ctx, `SELECT connection.source_type,connection.name,intent.relative_path,intent.name,
intent.size_bytes,intent.modified_at,intent.locator_hash,intent.fetch_state
FROM catalog_import_intents intent
JOIN source_connections connection ON connection.id=intent.source_connection_id
WHERE intent.source_connection_id=$1 AND intent.node_id=$2`, connectionID, nodeID).
Scan(&manifest.SourceType, &manifest.SourceName, &manifest.RelativePath, &manifest.Name,
&manifest.SizeBytes, &manifest.ModifiedAt, &manifest.LocatorHash, &fetchState)
if errors.Is(err, pgx.ErrNoRows) {
return artifactfetch.Manifest{}, artifactfetch.ErrManifestGone
}
if err != nil {
return artifactfetch.Manifest{}, fmt.Errorf("load artifact fetch manifest: %w", err)
}
if fetchState == "filtered" {
return artifactfetch.Manifest{}, artifactfetch.ErrManifestFiltered
}
var filtered bool
if err := db.QueryRow(ctx, `SELECT filename_is_filtered($1,$2,$3)`, connectionID, manifest.RelativePath, manifest.Name).Scan(&filtered); err != nil {
return artifactfetch.Manifest{}, fmt.Errorf("evaluate artifact filename filter: %w", err)
}
if filtered {
return artifactfetch.Manifest{}, artifactfetch.ErrManifestFiltered
}
manifest.ConnectionID = connectionID
manifest.NodeID = nodeID
return manifest, nil
}