context.go

v0.1.0
Doc Versions Source
1
package steward
2
3
import (
4
	"context"
5
	"sync"
6
7
	"github.com/soverenio/vanilla/throw"
8
)
9
10
func mustValueFromContext[T any](ctx context.Context, key any) T {
11
	val, ok := ctx.Value(key).(T)
12
	if !ok {
13
		panic("missing required context value")
14
	}
15
	return val
16
}
17
18
type initScopeKey struct{}
19
20
type InitScope interface {
21
	AddComponent(ctx context.Context, components ...Asset) // we should put here already initialized components
22
}
23
24
type initScope struct {
25
	lock    sync.Mutex
26
	status  bool
27
	manager *Manager
28
}
29
30
func (m *initScope) AddComponent(ctx context.Context, components ...Asset) {
31
	m.lock.Lock()
32
	defer m.lock.Unlock()
33
34
	if !m.status {
35
		panic(throw.IllegalState()) // initScope.AddComponent was called after component.Init was stopped
36
	}
37
38
	for _, component := range components {
39
		svcComponent, ok := component.(*serviceAsset)
40
		if !ok {
41
			continue
42
		}
43
44
		m.manager.inject(ctx, svcComponent)
45
	}
46
47
	m.manager._addComponent(ctx, components...)
48
}
49
50
func (m *initScope) Done(_ context.Context) {
51
	m.lock.Lock()
52
	defer m.lock.Unlock()
53
54
	if !m.status {
55
		panic(throw.IllegalState()) // initScope.Done was called twice
56
	}
57
	m.status = false
58
}
59
60
func InitScopeFromContext(ctx context.Context) InitScope {
61
	return mustValueFromContext[InitScope](ctx, initScopeKey{})
62
}
63
64
func withInitScope(ctx context.Context, manager *Manager) (context.Context, *initScope) {
65
	wrapper := &initScope{manager: manager, status: true}
66
	return context.WithValue(ctx, initScopeKey{}, wrapper), wrapper
67
}
68
69
type startScopeKey struct{}
70
71
type StartScope interface {
72
	CreateChildManager(ctx context.Context) *Manager
73
}
74
75
type startScope struct {
76
	lock    sync.Mutex
77
	status  bool
78
	manager *Manager
79
}
80
81
func StartScopeFromContext(ctx context.Context) StartScope {
82
	return mustValueFromContext[StartScope](ctx, startScopeKey{})
83
}
84
85
func WithStartScope(ctx context.Context, manager *Manager) (context.Context, StartScope) {
86
	return withStartScope(ctx, manager)
87
}
88
89
func withStartScope(ctx context.Context, manager *Manager) (context.Context, *startScope) {
90
	wrapper := &startScope{manager: manager, status: true}
91
	return context.WithValue(ctx, startScopeKey{}, wrapper), wrapper
92
}
93
94
func (m *startScope) CreateChildManager(_ context.Context) *Manager {
95
	m.lock.Lock()
96
	defer m.lock.Unlock()
97
98
	if !m.status {
99
		panic(throw.IllegalState()) // startScope.CreateChildManager was called after component.Start was stopped
100
	}
101
102
	return NewChildManager(m.manager)
103
}
104
105
func (m *startScope) Done(_ context.Context) {
106
	m.lock.Lock()
107
	defer m.lock.Unlock()
108
109
	if !m.status {
110
		panic(throw.IllegalState()) // startScope.Done was called twice
111
	}
112
	m.status = false
113
}
114

Source Files