Last active
November 14, 2022 07:25
-
-
Save terut/2c265388cfc3735bfe11494d3c11834b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
version: '3' | |
services: | |
# Spanner | |
spanner-emulator: | |
image: gcr.io/cloud-spanner-emulator/emulator | |
ports: | |
- "9010:9010" | |
- "9020:9020" | |
# Init (Create Instance) | |
spanner-emulator-init: | |
image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim | |
command: > | |
bash -c 'gcloud config configurations create emulator; | |
gcloud config set auth/disable_credentials true; | |
gcloud config set project $${PROJECT_ID}; | |
gcloud config set api_endpoint_overrides/spanner $${SPANNER_EMULATOR_URL}; | |
gcloud spanner instances create $${INSTANCE_NAME} --config=emulator-config --description=Emulator --nodes=1; | |
gcloud spanner databases create $${DATABASE_NAME} --instance=$${INSTANCE_NAME}' | |
# linux only | |
#extra_hosts: | |
# - "host.docker.internal:host-gateway" | |
environment: | |
PROJECT_ID: "test-project" | |
SPANNER_EMULATOR_URL: "http://spanner-emulator:9020/" | |
INSTANCE_NAME: "test-instance" | |
DATABASE_NAME: "test-database" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fixture | |
import ( | |
"context" | |
"fmt" | |
"reflect" | |
"cloud.google.com/go/spanner" | |
) | |
type Fixture struct { | |
Cli *spanner.Client | |
} | |
func (f *Fixture) Setup(ctx context.Context, seed []Seed) (func() error, error) { | |
msIns, msDel, err := CreateMutations(seed) | |
if err != nil { | |
return nil, err | |
} | |
if _, err := f.Cli.Apply(ctx, msIns); err != nil { | |
return nil, err | |
} | |
return func() error { | |
_, err := f.Cli.Apply(ctx, msDel) | |
return err | |
}, nil | |
} | |
func CreateMutations(seed []Seed) ([]*spanner.Mutation, []*spanner.Mutation, error) { | |
var msIns []*spanner.Mutation | |
var msDel []*spanner.Mutation | |
for _, ss := range seed { | |
keys := make([]spanner.Key, 0, len(ss.List)) | |
for _, s := range ss.List { | |
mi, err := spanner.InsertStruct(ss.Table, s) | |
if err != nil { | |
return nil, nil, err | |
} | |
msIns = append(msIns, mi) | |
k, err := key(reflect.ValueOf(s)) | |
if err != nil { | |
return nil, nil, err | |
} | |
keys = append(keys, k) | |
} | |
msDel = append(msDel, spanner.Delete(ss.Table, spanner.KeySetFromKeys(keys...))) | |
} | |
for i := len(msDel)/2 - 1; i >= 0; i-- { | |
opp := len(msDel) - 1 - i | |
msDel[i], msDel[opp] = msDel[opp], msDel[i] | |
} | |
return msIns, msDel, nil | |
} | |
func key(v reflect.Value) (spanner.Key, error) { | |
rt := v.Type() | |
if rt.Kind() == reflect.Ptr { | |
return key(v.Elem()) | |
} | |
if rt.Kind() != reflect.Struct { | |
return nil, err(fmt.Errorf("invalid seed type %v, use struct", rt.Kind())) | |
} | |
var key spanner.Key | |
for i := 0; i < rt.NumField(); i++ { | |
f := rt.Field(i) | |
if f.Tag.Get("fixture") != "key" { | |
continue | |
} | |
key = append(key, v.FieldByName(f.Name).Interface()) | |
} | |
return key, nil | |
} | |
type Seed struct { | |
Table string | |
List []any | |
} | |
func err(msg any) error { | |
return fmt.Errorf("fixture/fixture: %v", msg) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Seed interface { | |
S() | |
} | |
func NewSeed(ss ...interface{}) [][]Seed { | |
seeds := make([][]Seed, 0, len(ss)) | |
for _, ssi := range ss { | |
ssVal := reflect.ValueOf(ssi) | |
switch ssVal.Kind() { | |
case reflect.Slice: | |
seed := make([]Seed, 0, ssVal.Len()) | |
for i := 0; i < ssVal.Len(); i++ { | |
si := ssVal.Index(i).Interface() | |
if s, ok := si.(Seed); ok { | |
seed = append(seed, s) | |
} | |
} | |
seeds = append(seeds, seed) | |
case reflect.Struct, reflect.Pointer: | |
si := ssVal.Interface() | |
if s, ok := si.(Seed); ok { | |
seeds = append(seeds, []Seed{s}) | |
} | |
} | |
} | |
return seeds | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type result struct { | |
server string | |
err error | |
} | |
var ( | |
ErrConfig = errors.New("config get error") | |
) | |
func conn() error { | |
servers := []string{"127.0.0.1:11211", "127.0.0.1:11211", "127.0.0.1:11211"} | |
resultChan := make(chan result, len(servers)) | |
wg := new(sync.WaitGroup) | |
for _, server := range servers { | |
wg.Add(1) | |
go func(server string) { | |
defer wg.Done() | |
nc, err := net.Dial("tcp", server) | |
if err != nil { | |
resultChan <- result{server: server, err: err} | |
} | |
defer nc.Close() | |
_, err = nc.Write([]byte("get key1\r\n")) | |
if err != nil { | |
resultChan <- result{server: server, err: err} | |
} | |
buf := make([]byte, 4096) | |
n, err := nc.Read(buf) | |
if err != nil { | |
resultChan <- result{server: server, err: err} | |
} | |
if strings.HasSuffix(string(buf[:n]), "ERROR\r\n") { | |
resultChan <- result{server: server, err: ErrConfig} | |
} | |
if string(buf[:n]) == "END\r\n" { | |
fmt.Println("cache miss") | |
} | |
fmt.Println(string(buf[:n])) | |
resultChan <- result{server: server, err: nil} | |
}(server) | |
} | |
go func() { | |
wg.Wait() | |
close(resultChan) | |
}() | |
for result := range resultChan { | |
if result.err != nil && errors.Is(result.err, ErrConfig) { | |
fmt.Printf("%v, server=%v\n", result.err, result.server) | |
} | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment