When using redis and cloud.google.com/go/datastore which is after V1.4.0, if the time.Time type member of the struct is uninitialized, the struct cannot be put to datastore.
Without redis, put work well.
Using cloud.google.com/go/datastore V1.3.0, put work well.
(Few days ago I updated go.mod, then my unittest failed. datastrore V1.3.0 is OK, V1.4.0 or later is fail.)
Below is my Test code.
package main
import (
orgdatastore "cloud.google.com/go/datastore"
"context"
"fmt"
"github.com/gomodule/redigo/redis"
"go.mercari.io/datastore"
"go.mercari.io/datastore/clouddatastore"
"go.mercari.io/datastore/dsmiddleware/rediscache"
"log"
"net"
"time"
)
type Entity struct {
Tp time.Time //About cloud.google.com/go/datastore, in v1.4.0 or later, redis will result in an error unless it is explicitly initialized. No error occurs to v1.3.0
P int
}
var ename string
var pname string
var eid string
func main() {
loc, err := time.LoadLocation("Asia/Tokyo")
if err != nil {
loc = time.FixedZone("Asia/Tokyo", 9*60*60)
}
time.Local = loc
ename = "Entity"
pname = "my-project"
eid = "eid"
//pattern_originalDatastore()
pattern_mercariDatastore(true, false)
pattern_mercariDatastore(true, true)
}
func pattern_mercariDatastore(withRedis, doInitTimeMember bool) {
dbkind := fmt.Sprintf("mercari_redis_%v_timeInit_%v", withRedis, doInitTimeMember)
fail := false
c := context.Background()
client := getMercariClient(c, withRedis)
defer client.Close()
k := client.NameKey(ename, eid, nil)
e := new(Entity)
if err := client.Get(c, k, e); err != nil {
//This is first get, then err shold not be nil.
//log.Printf("%s Get Error %v\n", dbkind, err)
} else {
log.Printf("%s initialize miss\n", dbkind)
fail = true
}
e.P = 50
if doInitTimeMember { //cloud.google.com/go/datastore in v1.4.0 or later, this is necessary.
e.Tp = time.Now()
}
if _, err := client.Put(c, k, e); err != nil {
log.Printf("%s Put Error %v\n", dbkind, err)
fail = true
}
e2 := new(Entity)
if err := client.Get(c, k, e2); err != nil {
log.Printf("%s Put Fail %v\n", dbkind, err)
fail = true
}
if e2.P != 50 {
log.Printf("%s Put Fail 50, now %d\n", dbkind, e2.P)
fail = true
}
e2.P = 100
client.Put(c, k, e2)
e3 := new(Entity)
if err := client.Get(c, k, e3); err != nil {
log.Printf("%s Put Fail %v\n", dbkind, err)
fail = true
}
if e3.P != 100 {
log.Printf("%s Put100 Fail \n", dbkind)
fail = true
}
client.Delete(c, k)
if fail {
log.Printf("----- %s Fail -----", dbkind)
} else {
log.Printf("----- %s OK -----", dbkind)
}
}
func pattern_originalDatastore() {
dbkind := "original"
fail := false
c := context.Background()
client, _ := orgdatastore.NewClient(c, pname)
defer client.Close()
k := orgdatastore.NameKey(ename, eid, nil)
e := new(Entity)
if err := client.Get(c, k, e); err != nil {
//This is first get, then err shold not be nil.
//log.Printf("%s Get Error %v\n", dbkind, err)
} else {
log.Printf("%s initialize miss\n", dbkind)
fail = true
}
e.P = 50
if _, err := client.Put(c, k, e); err != nil {
log.Printf("%s Put Error %v\n", dbkind, err)
fail = true
}
e2 := new(Entity)
if err := client.Get(c, k, e2); err != nil {
log.Printf("%s Put Fail %v\n", dbkind, err)
fail = true
}
if e2.P != 50 {
log.Printf("%s Put Fail 50, now %d\n", dbkind, e2.P)
fail = true
}
e2.P = 100
client.Put(c, k, e2)
e3 := new(Entity)
if err := client.Get(c, k, e3); err != nil {
log.Printf("%s Put Fail %v\n", dbkind, err)
fail = true
}
if e3.P != 100 {
log.Printf("%s Put100 Fail \n", dbkind)
fail = true
}
client.Delete(c, k)
if fail {
log.Printf("----- %s Fail -----", dbkind)
} else {
log.Printf("----- %s OK -----", dbkind)
}
}
func getMercariClient(c context.Context, withredis bool) datastore.Client {
orgClient, _ := orgdatastore.NewClient(c, "my-project")
client, _ := clouddatastore.FromClient(c, orgClient)
dial, err := net.Dial("tcp", "localhost:6379")
if err != nil {
log.Printf("getMercariClient %v", err)
}
if withredis {
conn := redis.NewConn(dial, 100*time.Millisecond, 100*time.Millisecond)
//defer conn.Close()
mw := rediscache.New(conn,
rediscache.WithLogger(func(ctx context.Context, format string, args ...interface{}) {
log.Printf(format, args...)
}))
rediscachemw := mw
client.AppendMiddleware(rediscachemw)
}
return client
}