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.
This commit is contained in:
85
platform/internal/meta/backfill_import.go
Normal file
85
platform/internal/meta/backfill_import.go
Normal file
@@ -0,0 +1,85 @@
|
||||
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 同 BackfillDefaultImportExport;tenantID=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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user