...
1 package functionchain
2
3 import (
4 "context"
5 "sync"
6 "time"
7
8 "golang.conradwood.net/go-easyops/errors"
9 )
10
11
14 type FunctionChain struct {
15 sync.Mutex
16 functions []*function_ref
17 signal_stop_to_enable bool
18 signal_stop_to_disable bool
19 }
20
21 type Function interface {
22 SetTo(ctx context.Context, activate bool) error
23 }
24
25 func NewFunctionChain() *FunctionChain {
26 return &FunctionChain{}
27 }
28
29 func (fc *FunctionChain) Add(f Function) *function_ref {
30 fc.Lock()
31 defer fc.Unlock()
32 fr := &function_ref{functions: []Function{f}}
33 fc.functions = append(fc.functions, fr)
34 return fr
35 }
36
37 func (fc *FunctionChain) SetTo(ctx context.Context, b bool) error {
38 fc.Lock()
39 defer fc.Unlock()
40 if len(fc.functions) == 0 {
41 return nil
42 }
43 stop_signal := &fc.signal_stop_to_disable
44 if b {
45 stop_signal = &fc.signal_stop_to_enable
46 }
47 *stop_signal = false
48 start_time := time.Now()
49 end_time := start_time.Add(time.Duration(30) * time.Second)
50 repeat := true
51 for repeat {
52 if *stop_signal {
53 break
54 }
55 if time.Now().After(end_time) {
56 return errors.Errorf("timeout enabling functionchain (%0.1fs)", time.Since(start_time).Seconds())
57 }
58 repeat = false
59 for _, frw := range fc.functions {
60 if *stop_signal {
61 break
62 }
63 frw.Lock()
64 if time.Now().After(end_time) {
65 frw.Unlock()
66 return errors.Errorf("timeout enabling functionchain (%0.1fs)", time.Since(start_time).Seconds())
67 }
68 err := frw.SetTo(ctx, b)
69 frw.Unlock()
70 if err != nil {
71 repeat = true
72 }
73 }
74 if repeat {
75 time.Sleep(time.Duration(100) * time.Millisecond)
76 }
77
78 }
79 return nil
80 }
81 func (fc *FunctionChain) Enable(ctx context.Context) error {
82 fc.signal_stop_to_disable = true
83 return fc.SetTo(ctx, true)
84
85 }
86 func (fc *FunctionChain) Disable(ctx context.Context) error {
87 fc.signal_stop_to_enable = true
88 return fc.SetTo(ctx, false)
89 }
90
View as plain text