aboutsummaryrefslogtreecommitdiff
path: root/state
diff options
context:
space:
mode:
authorsangtran <tranquangsang12.7@gmail.com>2026-09-03 22:29:59 +0700
committersangtran <tranquangsang12.7@gmail.com>2026-09-03 22:29:59 +0700
commit93d5338d67b50d37b60e3fdda86be471ba20c6b2 (patch)
treedb6bdaf0b9b2bd08ba4ae6912ea1b018a230a2db /state
parent6631d8b00e8c5bafea15ea24415c5b55439193ee (diff)
signatureVerified sangtran <tranquangsang12.7@gmail.com> Key: 8DD79823D235E1BB ultimate trust
downloadflux-93d5338d67b50d37b60e3fdda86be471ba20c6b2.tar.gz
flux-93d5338d67b50d37b60e3fdda86be471ba20c6b2.zip
Verified feat: Add on pebble state backend support pebbledb
Diffstat (limited to 'state')
-rw-r--r--state/memory_backend.go2
-rw-r--r--state/pebble_backend.go126
2 files changed, 128 insertions, 0 deletions
diff --git a/state/memory_backend.go b/state/memory_backend.go
index f4043a1..dda577e 100644
--- a/state/memory_backend.go
+++ b/state/memory_backend.go
@@ -24,6 +24,8 @@ func NewMemoryStateBackend(maxParallelism int) *MemoryStateBackend {
24 return &MemoryStateBackend{ 24 return &MemoryStateBackend{
25 maxParallelism: maxParallelism, 25 maxParallelism: maxParallelism,
26 states: make(map[string]map[int]map[string]map[any]any), 26 states: make(map[string]map[int]map[string]map[any]any),
27 // default is void namespace
28 currentNamespace: core.VoidNamespace{},
27 } 29 }
28} 30}
29 31
diff --git a/state/pebble_backend.go b/state/pebble_backend.go
new file mode 100644
index 0000000..e428988
--- /dev/null
+++ b/state/pebble_backend.go
@@ -0,0 +1,126 @@
1package state
2
3import (
4 "context"
5 "encoding/binary"
6 "fmt"
7 "sync"
8
9 "flux/core"
10
11 "github.com/cockroachdb/pebble/v2"
12)
13
14type PebbleStateBackend struct {
15 maxParallelism int
16 currentKey string
17 currentGroupKey int
18 currentNamespace any
19 db *pebble.DB
20
21 // for support statename storage optimize
22 // PebbleDB dont have column family as RockDB does
23 // manually convert name <-> id
24 mu sync.Mutex
25 stateMap map[string]uint8
26 // nextStateID prevent the hash collision
27 nextStateID uint8
28}
29
30func NewPebbleStateBackend(dir string, maxParalleism int) (*PebbleStateBackend, error) {
31 db, err := pebble.Open(dir, &pebble.Options{})
32 if err != nil {
33 return nil, fmt.Errorf("failed to open pebbledb %w", err)
34 }
35 return &PebbleStateBackend{
36 maxParallelism: maxParalleism,
37 db: db,
38 stateMap: make(map[string]uint8),
39 nextStateID: 1,
40 }, nil
41}
42
43func (p *PebbleStateBackend) SetCurrentKey(key string) error {
44 p.currentKey = key
45 p.currentGroupKey = core.AssignToKeyGroup(key, p.maxParallelism)
46 return nil
47}
48
49func (p *PebbleStateBackend) GetCurrentKey() string {
50 return p.currentKey
51}
52
53func (p *PebbleStateBackend) SetCurrentNamespace(namespace any) error {
54 p.currentNamespace = namespace
55 return nil
56}
57
58func (p *PebbleStateBackend) GetCurrentNamespace() any {
59 return p.currentNamespace
60}
61
62// GetValueState(ctx context.Context, key string) (ValueState[any], error)
63func (p *PebbleStateBackend) GetValueState(ctx context.Context, statename string) (core.ValueState[any], error) {
64 stateID := p.getStateID(statename)
65 return nil, nil
66}
67
68func (p *PebbleStateBackend) getStateID(statename string) uint8 {
69 p.mu.Lock()
70 defer p.mu.Unlock()
71
72 if _, ok := p.stateMap[statename]; !ok {
73
74 id := p.nextStateID
75 p.stateMap[statename] = id
76 p.nextStateID++
77 }
78
79 return p.stateMap[statename]
80}
81
82func (p *PebbleStateBackend) calculateNamespaceSize() int {
83 nsLen := 0
84 switch p.currentNamespace.(type) {
85 case core.TimeWindow:
86 nsLen = 16
87 case string:
88 nsLen = len(p.currentNamespace.(string))
89 default:
90 // void namespace
91 nsLen = 0
92 }
93
94 return nsLen
95}
96
97func (p *PebbleStateBackend) deserialize(statename string) []byte {
98 // this will store in SSTable, order is important, keygroup MUST be first for scaling
99 // 2B(KeyGroup) + 1B(StateID) + 2B(KeyLen) + len(Key) + 16B(Window)
100
101 kl := len(p.currentKey)
102 b := make([]byte, 0, p.calculateNamespaceSize()+5+kl)
103
104 // add keygroup
105 b = binary.BigEndian.AppendUint16(b, uint16(p.currentGroupKey))
106
107 // add state id
108 stateID := p.getStateID(statename)
109 b = append(b, stateID)
110
111 // add key
112 b = binary.BigEndian.AppendUint16(b, uint16(kl))
113 b = append(b, p.currentKey...)
114
115 // add window / namespace
116
117 switch ns := p.currentNamespace.(type) {
118 case core.TimeWindow:
119 b = binary.BigEndian.AppendUint64(b, uint64(ns.Start))
120 b = binary.BigEndian.AppendUint64(b, uint64(ns.End))
121 case string:
122 b = append(b, ns...)
123 default:
124 }
125 return b
126}