mirror of https://github.com/tailscale/tailscale/
ipn: avoid useless no-op WriteState calls
Rather than make each ipn.StateStore implementation guard against useless writes (a write of the same value that's already in the store), do writes via a new wrapper that has a fast path for the unchanged case. This then fixes profileManager's flood of useless writes to AWS SSM, etc. Updates #8785 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>pull/8808/head
parent
a3f11e7710
commit
c56e94af2d
@ -0,0 +1,48 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package ipn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"tailscale.com/util/mak"
|
||||
)
|
||||
|
||||
type memStore struct {
|
||||
mu sync.Mutex
|
||||
writes int
|
||||
m map[StateKey][]byte
|
||||
}
|
||||
|
||||
func (s *memStore) ReadState(k StateKey) ([]byte, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return bytes.Clone(s.m[k]), nil
|
||||
}
|
||||
|
||||
func (s *memStore) WriteState(k StateKey, v []byte) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
mak.Set(&s.m, k, bytes.Clone(v))
|
||||
s.writes++
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestWriteState(t *testing.T) {
|
||||
var ss StateStore = new(memStore)
|
||||
WriteState(ss, "foo", []byte("bar"))
|
||||
WriteState(ss, "foo", []byte("bar"))
|
||||
got, err := ss.ReadState("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if want := []byte("bar"); !bytes.Equal(got, want) {
|
||||
t.Errorf("got %q; want %q", got, want)
|
||||
}
|
||||
if got, want := ss.(*memStore).writes, 1; got != want {
|
||||
t.Errorf("got %d writes; want %d", got, want)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue