aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/state/join.go
blob: 43a19b1dd56598519d0d0afaec38b66ba70f836e (plain)
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
package state

import (
	"errors"
	"maps"

	"hakurei.app/hst"
)

var (
	ErrDuplicate = errors.New("store contains duplicates")
)

/*
Joiner is the interface that wraps the Join method.

The Join function uses Joiner if available.
*/
type Joiner interface {
	Join() (map[hst.ID]*hst.State, error)
}

// Join returns joined state entries of all active identities.
func Join(s Store) (map[hst.ID]*hst.State, error) {
	if j, ok := s.(Joiner); ok {
		return j.Join()
	}

	var (
		aids    []int
		entries = make(map[hst.ID]*hst.State)

		el      int
		res     map[hst.ID]*hst.State
		loadErr error
	)

	if ln, err := s.List(); err != nil {
		return nil, err
	} else {
		aids = ln
	}

	for _, aid := range aids {
		if _, err := s.Do(aid, func(c Cursor) {
			res, loadErr = c.Load()
		}); err != nil {
			return nil, err
		}

		if loadErr != nil {
			return nil, loadErr
		}

		// save expected length
		el = len(entries) + len(res)
		maps.Copy(entries, res)
		if len(entries) != el {
			return nil, ErrDuplicate
		}
	}

	return entries, nil
}