File: singleton.go

package info (click to toggle)
golang-github-mesos-mesos-go 0.0.6%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 11,724 kB
  • sloc: makefile: 163
file content (160 lines) | stat: -rw-r--r-- 3,125 bytes parent folder | download
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package store

import (
	"sync/atomic"
)

type (
	Getter interface {
		Get() (string, error)
	}

	GetFunc func() (string, error)

	Setter interface {
		Set(string) error
	}

	SetFunc func(string) error

	// Singleton is a thread-safe abstraction to load and store a string
	Singleton interface {
		Getter
		Setter
	}

	SingletonAdapter struct {
		GetFunc
		SetFunc
	}

	SingletonDecorator interface {
		Decorate(Singleton) Singleton
	}

	Error string
)

func (err Error) Error() string { return string(err) }

const ErrNotFound = Error("value not found in store")

func (f GetFunc) Get() (string, error) { return f() }
func (f SetFunc) Set(s string) error   { return f(s) }

func NewInMemorySingleton() Singleton {
	var value atomic.Value
	return &SingletonAdapter{
		func() (string, error) {
			x := value.Load()
			if x == nil {
				return "", ErrNotFound
			}
			return x.(string), nil
		},
		func(s string) error {
			value.Store(s)
			return nil
		},
	}
}

type (
	GetFuncDecorator func(Getter, string, error) (string, error)
	SetFuncDecorator func(Setter, string, error) error
)

func DoSet() SetFuncDecorator {
	return func(s Setter, v string, _ error) error {
		return s.Set(v)
	}
}

func (f SetFuncDecorator) AndThen(f2 SetFuncDecorator) SetFuncDecorator {
	return func(s Setter, v string, err error) error {
		err = f(s, v, err)
		if err != nil {
			return err
		}
		return f2(s, v, nil)
	}
}

func (f SetFuncDecorator) Decorate(s Singleton) Singleton {
	if f == nil {
		return s
	}
	return &SingletonAdapter{
		s.Get,
		SetFunc(func(v string) error {
			return f(s, v, nil)
		}),
	}
}

func DoGet() GetFuncDecorator {
	return func(s Getter, _ string, _ error) (string, error) {
		return s.Get()
	}
}

func (f GetFuncDecorator) AndThen(f2 GetFuncDecorator) GetFuncDecorator {
	return func(s Getter, v string, err error) (string, error) {
		v, err = f(s, v, err)
		if err != nil {
			return v, err
		}
		return f2(s, v, nil)
	}
}

func (f GetFuncDecorator) Decorate(s Singleton) Singleton {
	if f == nil {
		return s
	}
	return &SingletonAdapter{
		GetFunc(func() (string, error) {
			return f(s, "", nil)
		}),
		s.Set,
	}
}

func DecorateSingleton(s Singleton, ds ...SingletonDecorator) Singleton {
	for _, d := range ds {
		if d != nil {
			s = d.Decorate(s)
		}
	}
	return s
}

// GetOrPanic curries the result of a Getter invocation: the returned func only ever returns the string component when
// the error component of the underlying Get() call is nil. If Get() generates an error then the curried func panics.
func GetOrPanic(g Getter) func() string {
	return func() string {
		v, err := g.Get()
		if err != nil {
			panic(err)
		}
		return v
	}
}

func GetIgnoreErrors(g Getter) func() string {
	return func() string {
		v, _ := g.Get()
		return v
	}
}

// SetOrPanic curries the result of a Setter invocation: the returned func only ever returns normally when the error
// component of the underlying Set() call is nil. If Set() generates an error then the curried func panics.
func SetOrPanic(s Setter) func(v string) {
	return func(v string) {
		err := s.Set(v)
		if err != nil {
			panic(err)
		}
	}
}