Skip to content

Commit f3755f6

Browse files
author
Aaron Schlesinger
committed
feat(pkg/sshd/circuit*): add a circuit primitive
it will be used in the health probe, so the builder isn’t considered up until the SSH server is actually running
1 parent f58ac45 commit f3755f6

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

pkg/sshd/circuit.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package sshd
2+
3+
import (
4+
"fmt"
5+
"sync/atomic"
6+
)
7+
8+
type CircuitState uint32
9+
10+
const (
11+
OpenState CircuitState = 0
12+
ClosedState CircuitState = 1
13+
)
14+
15+
func (c CircuitState) String() string {
16+
if c == OpenState {
17+
return "OPEN"
18+
} else if c == ClosedState {
19+
return "CLOSED"
20+
} else {
21+
return fmt.Sprintf("Unknown (%d)", c.toUint32())
22+
}
23+
}
24+
25+
func (s CircuitState) toUint32() uint32 {
26+
return uint32(s)
27+
}
28+
29+
// Circuit is a concurrency-safe data structure that can take one of two states at any point in time:
30+
//
31+
// - OpenState - non functional
32+
// - ClosedState - functional
33+
//
34+
//
35+
type Circuit struct {
36+
bit uint32
37+
}
38+
39+
func NewCircuit() *Circuit {
40+
return &Circuit{bit: OpenState.toUint32()}
41+
}
42+
43+
// State returns the current state of the circuit. Note that concurrent modifications may be happening, so the state may be different than what's returned
44+
func (c *Circuit) State() CircuitState {
45+
return CircuitState(atomic.LoadUint32(&c.bit))
46+
}
47+
48+
// Close closes the circuit if it wasn't already closed. Returns true if it had to be closed, false if it was already closed
49+
func (c *Circuit) Close() bool {
50+
return atomic.CompareAndSwapUint32(&c.bit, OpenState.toUint32(), ClosedState.toUint32())
51+
}
52+
53+
// Open opens the circuit if it wasn't already closed. Returns true if it had to be opened, false if it was already open
54+
func (c *Circuit) Open() bool {
55+
return atomic.CompareAndSwapUint32(&c.bit, ClosedState.toUint32(), OpenState.toUint32())
56+
}

pkg/sshd/circuit_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package sshd
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestOpenCloseSerial(t *testing.T) {
8+
c := NewCircuit()
9+
if c.State() != OpenState {
10+
t.Fatalf("unexpected initial circuit state. want %s, got %s", OpenState, c.State())
11+
}
12+
if b := c.Close(); !b {
13+
t.Fatalf("tried to close the circuit but it said it was already closed")
14+
}
15+
if c.State() != ClosedState {
16+
t.Fatalf("unexpected circuit state. want %s, got %s", ClosedState, c.State())
17+
}
18+
if b := c.Open(); !b {
19+
t.Fatalf("tried to open the circuit but it said it was already opened")
20+
}
21+
if c.State() != OpenState {
22+
t.Fatalf("unexpected circuit state. want %s, got %s", OpenState, c.State())
23+
}
24+
}
25+
26+
func TestOpenCloseConcurrent(t *testing.T) {
27+
28+
}

0 commit comments

Comments
 (0)