SharedInformerFactory

20240301001916

使用简化代码描述SharedInformerFactory

工厂

我们先定义了一个工厂接口,此接口InformerFor函数是构造某个资源的SharedIndexInformer需要知道资源以及构造这个资源SharedIndexInformer的方法,有点绕,大概意思就是这个函数其实不知道怎么构造资源的SharedIndexInformer,都是需要入参提供的,自身是非常的通用。

1
2
3
4
5
6
7
8
type FactoryI interface {
	InformerFor(resource any, constructF ConstructFuncForInformerI) SharedIndexInformer
}
type SharedIndexInformer interface {
	// 包含很多方法,具体是什么方法后面再说
}

type ConstructFuncForInformerI func(client http.Client) SharedIndexInformer

我们再来看FactoryI的实现,聚焦于InformerFor函数,如上讨论,这个里面没有具体某个资源SharedIndexInformer生成逻辑,只是有一个缓存。这里好处如下:

  1. 当某个资源调用过一次InformerFor后,后续再调用就可以直接从缓存中拿就行了。
  2. 可以记录所有生成过SharedIndexInformer的资源。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
type Factory struct {
	cache  map[reflect.Type]SharedIndexInformer
	client http.Client
}

func (f *Factory) InformerFor(resource any, constructF ConstructFuncForInformerI) SharedIndexInformer {
	curType := reflect.TypeOf(resource)
	if v, ok := f.cache[curType]; ok {
		return v
	} else {
		f.cache[curType] = constructF(f.client)
		return f.cache[curType]
	}
}

调用InformerFor方法

那么Factory的InformerFor方法再哪里被调用呢? 继续来看Factory的另一个方法,它是用户自己定义的一个资源(可类比与deployment,pod等),它的响应是一个组方法,继续跟踪下去可以看到有版本,然后是Informer,这个Informer有Informer方法以及一个私有的构造SharedIndexInformer接口的方法。 而且工厂自身也被依次的传递了下去,直到Informer函数里调用了工厂的InformerFor方法。

 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
func (f *Factory) 我自己定义的资源() GroupInterfaceI {
	return NewGroupInterface(f)
}

type GroupInterfaceI interface {
	V1ByXXX() VersionInterfaceI
}
func NewGroupInterface(f FactoryI) GroupInterfaceI {
	return &GroupInterface{
		f: f,
	}
}
type GroupInterface struct {
	f FactoryI
}
func (g *GroupInterface) V1ByXXX() VersionInterfaceI {
	return NewVersionInterface(g.f)
}


type VersionInterfaceI interface {
	KindByXXX() XXXInformerI
}
func NewVersionInterface(f FactoryI) VersionInterfaceI {
	return &VersionInterface{
		f: f,
	}
}
type VersionInterface struct {
	f FactoryI
}
func (g *VersionInterface) KindByXXX() XXXInformerI {
	return NewXXXInformer(g.f)
}

type 我自己定义的资源InformerI interface {
	Informer() SharedIndexInformer
}
func New我自己定义的资源Informer(f FactoryI) XXXInformerI {
	return &XXXInformer{
		factory: f,
	}
}
type 我自己定义的资源Informer struct {
	factory FactoryI
}
func (x *我自己定义的资源Informer) Informer() SharedIndexInformer {
	return x.factory.InformerFor(我自己定义的资源Informer{}, x.defaultInformer)
}

func (x *我自己定义的资源Informer) defaultInformer(client http.Client) SharedIndexInformer {
	// panic("implement me")
	return nil
}
var _ ConstructFuncForInformerI = 我自己定义的资源Informer{}.defaultInformer

到这里也就看明白了Factory方法以及Factory具体实现以及自定义资源的Informer的大致调用过程。资源对应的SharedIndexInformer还是由自身来决定怎么实现。工厂只是提供了InformerFor方法,来缓存所有资源的SharedIndexInformer。