zhangqian
2023-10-13 13194e787d51e4ce07dfc35341d536fb5db7aaa3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package service
 
import (
    "aps_crm/pkg/logx"
    "context"
    "errors"
    "sort"
)
 
// SubInitializer 提供 source/*/init() 使用的接口,每个 initializer 完成一个初始化过程
type SubInitializer interface {
    InitializerName() string // 不一定代表单独一个表,所以改成了更宽泛的语义
    InitializeData(ctx context.Context) (next context.Context, err error)
    DataInserted(ctx context.Context) bool
}
 
// orderedInitializer 组合一个顺序字段,以供排序
type orderedInitializer struct {
    order int
    SubInitializer
}
 
// initSlice 供 initializerList 排序依赖时使用
type initSlice []*orderedInitializer
 
func (a initSlice) Len() int {
    return len(a)
}
 
func (a initSlice) Less(i, j int) bool {
    return a[i].order < a[j].order
}
 
func (a initSlice) Swap(i, j int) {
    a[i], a[j] = a[j], a[i]
}
 
var (
    initializerList initSlice                      // 初始化列表
    initializerMap  map[string]*orderedInitializer // 初始化map
)
 
// RegisterInit 注册要执行的初始化过程,会在 InitDB() 时调用
func RegisterInit(order int, subInit SubInitializer) {
    if initializerList == nil {
        initializerList = initSlice{}
    }
    if initializerMap == nil {
        initializerMap = map[string]*orderedInitializer{}
    }
    subInitName := subInit.InitializerName()
    if _, existed := initializerMap[subInitName]; existed {
        logx.Errorf("Name conflict on %s", subInitName)
        return
    }
    orderedSubInit := orderedInitializer{order, subInit}
    initializerList = append(initializerList, &orderedSubInit)
    initializerMap[subInitName] = &orderedSubInit
}
 
type InitDBService struct{}
 
// InitDB 初始化
func (initDBService *InitDBService) InitDB() (err error) {
    if len(initializerList) == 0 {
        return errors.New("无可用初始化过程,请检查初始化是否已执行完成")
    }
    sort.Sort(&initializerList) // 保证有依赖的 initializer 排在后面执行
 
    initHandler := NewMysqlInitHandler()
    if err = initHandler.InitData(context.TODO(), initializerList); err != nil {
        logx.Errorf("InitDB InitData err:%v", err)
        return err
    }
 
    initializerList = initSlice{}
    initializerMap = map[string]*orderedInitializer{}
    return nil
}