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>main
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