[perf]]Add namespaces to memcached cache.Cache implementation.

Change-Id: I29c49836f47503b86a9a710e9cb1f1c5d5e12b66
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/305897
Reviewed-by: Joe Gregorio <jcgregorio@google.com>
Commit-Queue: Joe Gregorio <jcgregorio@google.com>
diff --git a/perf/go/cache/memcached/memcached.go b/perf/go/cache/memcached/memcached.go
index 29986b1..582babb 100644
--- a/perf/go/cache/memcached/memcached.go
+++ b/perf/go/cache/memcached/memcached.go
@@ -12,31 +12,40 @@
 // Cache implements the cache.Cache interface.
 type Cache struct {
 	client *memcache.Client
+
+	// namespace is the string to add to each key to avoid conflicts with more
+	// than one application or application instance using the same memcached
+	// server.
+	namespace string
 }
 
 // New returns a new in-memory cache of the given size.
-func New(server ...string) (*Cache, error) {
-	c := memcache.New(server...)
+//
+// The namespace is the string to add to each key to avoid conflicts with more
+// than one application or application instance using the same memcached server.
+func New(servers []string, namespace string) (*Cache, error) {
+	c := memcache.New(servers...)
 	c.Timeout = time.Second * 5
 	return &Cache{
-		client: c,
+		client:    c,
+		namespace: namespace,
 	}, c.Ping()
 }
 
 // Add implements the cache.Cache interface.
 func (c *Cache) Add(key string, value string) {
-	err := c.client.Add(&memcache.Item{
-		Key:   key,
+	err := c.client.Set(&memcache.Item{
+		Key:   key + c.namespace,
 		Value: []byte(value),
 	})
 	if err != nil {
-		sklog.Errorf("Memcached failed to write: %s", err)
+		sklog.Errorf("Memcached failed to write: [%q: %q] %s", key, value, err)
 	}
 }
 
 // Get implements the cache.Cache interface.
 func (c *Cache) Get(key string) (string, bool) {
-	item, err := c.client.Get(key)
+	item, err := c.client.Get(key + c.namespace)
 	if err != nil {
 		if err != memcache.ErrCacheMiss {
 			sklog.Errorf("Memcached failed to get: %s", err)
@@ -48,7 +57,7 @@
 
 // Exists implements the cache.Cache interface.
 func (c *Cache) Exists(key string) bool {
-	_, err := c.client.Get(key)
+	_, err := c.client.Get(key + c.namespace)
 	return err == nil
 }
 
diff --git a/perf/go/cache/memcached/memcached_test.go b/perf/go/cache/memcached/memcached_test.go
index f6e7873..e04ee4b 100644
--- a/perf/go/cache/memcached/memcached_test.go
+++ b/perf/go/cache/memcached/memcached_test.go
@@ -8,17 +8,17 @@
 	"go.skia.org/infra/go/testutils/unittest"
 )
 
-const localServerAddress = "127.0.0.1:11211"
+var localServerAddress = []string{"127.0.0.1:11211"}
 
 func TestCache_New_Failure(t *testing.T) {
 	unittest.ManualTest(t)
-	_, err := New("")
+	_, err := New([]string{""}, "")
 	require.Error(t, err)
 }
 
 func TestCache_Get_Success(t *testing.T) {
 	unittest.ManualTest(t)
-	c, err := New(localServerAddress)
+	c, err := New(localServerAddress, "test-namespace")
 	require.NoError(t, err)
 
 	c.Add("foo", "bar")
@@ -32,7 +32,7 @@
 
 func TestCache_Get_FalseOnMiss(t *testing.T) {
 	unittest.ManualTest(t)
-	c, err := New(localServerAddress)
+	c, err := New(localServerAddress, "test-namespace")
 	require.NoError(t, err)
 
 	_, ok := c.Get("quux")
@@ -41,21 +41,36 @@
 
 func TestCache_Exists_Success(t *testing.T) {
 	unittest.ManualTest(t)
-	c, err := New(localServerAddress)
+	c, err := New(localServerAddress, "test-namespace")
 	require.NoError(t, err)
 
-	c.Add("foo", "bar")
+	c.Add("foo", "baz")
 	ok := c.Exists("foo")
 	assert.True(t, ok)
 }
 
-func TestCache_Exists_FalseOnMiss(t *testing.T) {
+func TestCache_ExistsOnlyInOneNamespace_Success(t *testing.T) {
 	unittest.ManualTest(t)
-	c, err := New(localServerAddress)
+	c, err := New(localServerAddress, "test-namespace")
 	require.NoError(t, err)
 
-	_ = c.client.Delete("foo")
-
+	c.Add("foo", "quux")
 	ok := c.Exists("foo")
+	assert.True(t, ok)
+
+	c, err = New(localServerAddress, "test-namespace-2")
+	require.NoError(t, err)
+
+	ok = c.Exists("foo")
+	assert.False(t, ok)
+
+}
+
+func TestCache_Exists_FalseOnMiss(t *testing.T) {
+	unittest.ManualTest(t)
+	c, err := New(localServerAddress, "test-namespace")
+	require.NoError(t, err)
+
+	ok := c.Exists("qux")
 	assert.False(t, ok)
 }