Using Predix Cache with Go

Get code samples and recommended libraries for using a Predix Cache service with Go.

Recommended Libraries
Radix. See https://github.com/mediocregopher/radix.v2
Alternative Libraries

Install the Library for Shared and Dedicated Single Node Service Plans

  • Godep:
    1. Run:
      go get github.com/mediocregopher/radix.v2/cache
    2. Run:
      go get github.com/cloudfoundry-community/go-cfenv
    3. Edit your code to import the cache client.
    4. Run:
      godep save ./...
  • Glide:
    1. Run:
      glide get github.com/mediocregopher/radix.v2/cache
    2. Run:
      glide get github.com/cloudfoundry-community/go-cfenv
    3. Run:
      glide install
    4. Your glide.yml file should look like the following:
      package: github.com/ge-digital/cache-single-sample
      import:
      - package: github.com/cloudfoundry-community/go-cfenv
        version: ~1.14.0
      - package: github.com/mediocregopher/radix.v2/cache

Shared and Dedicated Single Node Service Plan Samples

Sample Cloud Foundry manifest
applications:
- name: cache-single-sample
  mem: 1024M
  disk: 1024M
  instances: 1
  services:
    - cache-shared-sample
radix Sample for Shared and Dedicated Single Node Service Plans
package main

import (
  "fmt"
  "log"
  "net/http"
  "os"

  cfenv "github.com/cloudfoundry-community/go-cfenv"
  "github.com/mediocregopher/radix.v2/cache"
)

const (
  // Specify Default Port if one isn't define in ENV
  DefaultPort = "3333"
)

func InfoServer(w http.ResponseWriter, req *http.Request) {

  appEnv, err := cfenv.Current()

  redis_services, err := appEnv.Services.WithLabel("predix-cache")
  redis_creds := redis_services[0]

  // Alternatively get Credentials given the Service Instance Name
  // redis_creds, err := appEnv.Services.WithName("cache-shared-sample")

  fmt.Fprintln(w, "\nCreds: ", redis_creds)
  fmt.Fprintln(w, "Host: ", redis_creds.Credentials["host"])
  fmt.Fprintln(w, "Port: ", redis_creds.Credentials["port"])
  fmt.Fprintln(w, "Password: ", redis_creds.Credentials["password"])

  connectStr := fmt.Sprintf("%v:%v", redis_creds.Credentials["host"], redis_creds.Credentials["port"])
  client, err := cache.Dial("tcp", connectStr)
  if err != nil {
    fmt.Fprintln(w, "Error: ", err)
  } else {
    fmt.Fprintln(w, "Client Connected!")
  }

  redis_pass := fmt.Sprintf("%v", redis_creds.Credentials["password"])
  auth, err := client.Cmd("AUTH", redis_pass).Str()
  if err != nil {
    fmt.Fprintln(w, "Error", err)
  } else {
    fmt.Fprintln(w, "Auth: ", auth)
  }

  foo, err := client.Cmd("SET", "foo", "bar").Str()
  if err != nil {
    fmt.Fprintln(w, "Error: ", err)
  } else {
    fmt.Fprintln(w, "SET Result: ", foo)
  }

  foo1, err := client.Cmd("GET", "foo").Str()
  if err != nil {
    fmt.Fprintln(w, "Error: ", err)
  } else {
    fmt.Fprintln(w, "GET Result: ", foo1)
  }
}

func main() {
  var port string
  if port = os.Getenv("PORT"); len(port) == 0 {
    log.Printf("Warning, PORT not set. Defaulting to %+v\n", DefaultPort)
    port = DefaultPort
  }

  http.HandleFunc("/", InfoServer)
  http_err := http.ListenAndServe(":"+port, nil)
  if http_err != nil {
    log.Printf("Listening On: %v\n", http_err)
  }
}
Validating Single Node Connectivity
To verify the application is able to connect, simply use CURL from the command line to retrieve the output:
$ curl https://cache-single-sample.run.aws-usw02-pr.ice.predix.io

Creds:  {cache-shared-sample predix-cache [cache] Free map[host:10.72.27.128 port:6043 password:password]}
Host:  10.72.27.128
Port:  6043
Password:  <password>
Client Connected!
Auth:  OK
SET Result:  OK
GET Result:  bar

Installing the Sentinel Library for High Availability Service Plans Using Sentinels

  • Godep:
    1. Run:
      go get github.com/mediocregopher/radix.v2/sentinel
    2. Run:
      go get github.com/cloudfoundry-community/go-cfenv
    3. Edit your code to import the packages.
    4. Run:
      godep save ./...
  • Glide:
    1. Run:
      glide get github.com/mediocregopher/radix.v2/sentinel
    2. Run:
      glide get github.com/cloudfoundry-community/go-cfenv
    3. Run:
      glide install
    4. Your glide.yml should look like the following:
      package: github.com/ge-digital/cache-single-sample
      import:
      - package: github.com/cloudfoundry-community/go-cfenv
        version: ~1.14.0
      - package: github.com/mediocregopher/radix.v2/sentinel

radix Sample for High Availability Service Plans using Sentinels

package main

import (
  "fmt"
  "log"
  "net/http"
  "os"
  "strings"

  cfenv "github.com/cloudfoundry-community/go-cfenv"
  "github.com/mediocregopher/radix.v2/sentinel"
)

const (
  // DefaultPort is the port in which to listen if there is no PORT declared
  DefaultPort = "3333"
)

func InfoServer(w http.ResponseWriter, req *http.Request) {

  appEnv, err := cfenv.Current()

  redis_services, err := appEnv.Services.WithLabel("predix-cache")
  redis_creds := redis_services[0]

  // Alternatively get Credentials given the Service Instance Name
  // redis_creds, err := appEnv.Services.WithName("cache-shared-sample")

  r := strings.NewReplacer("[", "", "]", "")
  sentinel_list := strings.Split(r.Replace(fmt.Sprintf("%v", redis_creds.Credentials["ip_list"])), " ")

  fmt.Fprintln(w, "\nCreds: ", redis_creds)
  fmt.Fprintln(w, "Host: ", redis_creds.Credentials["host"])
  fmt.Fprintln(w, "Port: ", redis_creds.Credentials["port"])
  fmt.Fprintln(w, "Sentine Port: ", redis_creds.Credentials["sentinel_port"])
  fmt.Fprintln(w, "IP List: ", sentinel_list)
  fmt.Fprintln(w, "Password: ", redis_creds.Credentials["password"])
  fmt.Fprintln(w, "Master Name: ", redis_creds.Credentials["master_name"])

  masterName := fmt.Sprintf("%v", redis_creds.Credentials["master_name"])

  connectStr := fmt.Sprintf("%v:%v", sentinel_list[0], redis_creds.Credentials["sentinel_port"])
  client, err := sentinel.NewClient("tcp", connectStr, 100, masterName)
  if err != nil {
    fmt.Fprintln(w, "Error Connecting to Sentinel: ", err)
    for i := range sentinel_list {
      connectStr := fmt.Sprintf("%v:%v", sentinel_list[i], redis_creds.Credentials["sentinel_port"])
      client, err = sentinel.NewClient("tcp", connectStr, 100, masterName)
      if err != nil {
        fmt.Fprintln(w, "Error Connecting to Sentinel: ", err)
      } else {
        break
      }
    }
  } else {
    fmt.Fprintln(w, "Client Connected!")
  }

  conn, err := client.GetMaster(masterName)
  if err != nil {
    fmt.Fprintln(w, "Error: ", err)
  }
  defer client.PutMaster(masterName, conn)

  redis_pass := fmt.Sprintf("%v", redis_creds.Credentials["password"])
  auth, err := conn.Cmd("AUTH", redis_pass).Str()
  if err != nil {
    fmt.Fprintln(w, "Error", err)
  } else {
    fmt.Fprintln(w, "Auth: ", auth)
  }

  foo, err := conn.Cmd("SET", "foo", "bar").Str()
  if err != nil {
    fmt.Fprintln(w, "Error: ", err)
  } else {
    fmt.Fprintln(w, "SET Result: ", foo)
  }

  foo1, err := conn.Cmd("GET", "foo").Str()
  if err != nil {
    fmt.Fprintln(w, "Error: ", err)
  } else {
    fmt.Fprintln(w, "GET Result: ", foo1)
  }
}

func main() {
  var port string
  if port = os.Getenv("PORT"); len(port) == 0 {
    log.Printf("Warning, PORT not set. Defaulting to %+v\n", DefaultPort)
    port = DefaultPort
  }

  http.HandleFunc("/", InfoServer)
  http_err := http.ListenAndServe(":"+port, nil)
  if http_err != nil {
    log.Printf("Listening On: %v\n", http_err)
  }
}