Files
ai_site/platform/internal/meta/backfill_import.go
whm cb56e6847e feat: add Z12/Z13 bind APIs, stock import, and sync docs
Enable auto default sync channels on agent activate, bind-code/phone confirm flows, publish ALTER, and align admin/yuheng docs with the production bind path.
2026-08-05 11:47:20 +08:00

86 lines
2.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package meta
import (
"context"
"encoding/json"
"fmt"
"log"
)
// BackfillImportResult Z9e 扫库补齐 import/export 的结果。
type BackfillImportResult struct {
Scanned int `json:"scanned"`
Updated int `json:"updated"`
Skipped int `json:"skipped"`
DryRun bool `json:"dry_run"`
Slugs []string `json:"updated_slugs,omitempty"`
Message string `json:"message,omitempty"`
}
// PublishedLister 列出全部已发布应用(跨租户,供 Z9e 启动扫库)。
type PublishedLister interface {
ListPublishedApps(ctx context.Context) ([]*AppRecord, error)
}
// BackfillDefaultImportExport 遍历已发布蓝图,对可写 resource 补齐 import/export 并落库Z9e
// dryRun=true 只统计不写库。tenantID>0 时仅处理该租户。
func BackfillDefaultImportExport(ctx context.Context, store Store, dryRun bool) (*BackfillImportResult, error) {
return BackfillDefaultImportExportForTenant(ctx, store, 0, dryRun)
}
// BackfillDefaultImportExportForTenant 同 BackfillDefaultImportExporttenantID=0 表示全库。
func BackfillDefaultImportExportForTenant(ctx context.Context, store Store, tenantID int64, dryRun bool) (*BackfillImportResult, error) {
if store == nil {
return nil, fmt.Errorf("meta store nil")
}
lister, ok := store.(PublishedLister)
if !ok {
return nil, fmt.Errorf("meta store does not support ListPublishedApps")
}
apps, err := lister.ListPublishedApps(ctx)
if err != nil {
return nil, err
}
out := &BackfillImportResult{DryRun: dryRun, Slugs: make([]string, 0)}
for _, app := range apps {
if app == nil || app.Blueprint == nil {
continue
}
if tenantID > 0 && app.TenantID != tenantID {
continue
}
out.Scanned++
before, _ := json.Marshal(app.Blueprint)
app.Blueprint.EnsureDefaultImportExport()
after, _ := json.Marshal(app.Blueprint)
if string(before) == string(after) {
out.Skipped++
continue
}
out.Updated++
out.Slugs = append(out.Slugs, fmt.Sprintf("%d/%s", app.TenantID, app.Slug))
if dryRun {
continue
}
if err := store.Save(ctx, app); err != nil {
return out, fmt.Errorf("save %s: %w", app.Slug, err)
}
}
out.Message = fmt.Sprintf("scanned=%d updated=%d skipped=%d dry_run=%v", out.Scanned, out.Updated, out.Skipped, dryRun)
return out, nil
}
// RunBackfillDefaultImportExportOnBoot 启动时扫库(失败只打日志,不阻断启动)。
func RunBackfillDefaultImportExportOnBoot(ctx context.Context, store Store) {
res, err := BackfillDefaultImportExport(ctx, store, false)
if err != nil {
log.Printf("Z9e backfill import ops: %v", err)
return
}
if res != nil && res.Updated > 0 {
log.Printf("Z9e backfill import ops: %s slugs=%v", res.Message, res.Slugs)
} else if res != nil {
log.Printf("Z9e backfill import ops: %s", res.Message)
}
}