func (d *Driver) SyncPut(key *datastore.Key, src Syncable) (*datastore.Key, error) { t := time.Now() typ := reflect.Indirect(reflect.ValueOf(src)).Type() // Get the struct type fieldName := src.TimestampFieldName() reflect.Indirect(reflect.ValueOf(src)).FieldByName(fieldName).Set(reflect.ValueOf(t)) if _, err := d.Put(key, src); err != nil { return nil, err } else { var _src = reflect.New(typ).Interface() err := wcg.RetryUntil(func() error { if err := d.Get(key, _src); err != nil { return err } else { t := reflect.Indirect(reflect.ValueOf(src)).FieldByName(fieldName).Interface().(time.Time) if t.Unix() == t.Unix() { return nil } else { return fmt.Errorf("put not synched.") } } }, d.Timeout*2, 500*time.Millisecond) if err != nil { return nil, &timeoutErr{err} } else { return key, nil } } }
func (d *Driver) SyncDelete(key *datastore.Key) error { if err := d.Delete(key); err != nil { return err } else { q := d.NewQuery().Filter("__key__ =", key) err := wcg.RetryUntil(func() error { if i, err := q.Count(); i == 0 { return nil } else { return fmt.Errorf("delete not synched: internal error?(%v)", err) } }, d.Timeout*2, 500*time.Millisecond) if err != nil { return &timeoutErr{err} } else { return nil } } }
func CleanupDatastore(ctx appengine.Context) error { var dummy []interface{} logger := wcg.NewLogger(nil) logger.Debug("[Fixture] --------- CleanupDatastore ---------") return wcg.RetryUntil(func() error { if keys, err := datastore.NewQuery("").KeysOnly().GetAll(ctx, dummy); err != nil { return err } else { if err := datastore.DeleteMulti(ctx, keys); err != nil { return err } count, _ := datastore.NewQuery("").KeysOnly().Count(ctx) if count == 0 { return nil } else { return fmt.Errorf("Still have %d keys.", count) } } }, 10*time.Second, 100*time.Millisecond) }
func loadJsonToDatastore(ctx appengine.Context, pkey *datastore.Key, data map[string]interface{}, logger wcg.Logger) error { var kind string var ns string var keyval interface{} var key *datastore.Key var ok bool var err error if _, ok = data["_kind"]; !ok { return fmt.Errorf("Missing key `_kind`") } else { kind = data["_kind"].(string) } if keyval, ok = data["_key"]; !ok { return fmt.Errorf("Missing key `_key`") } if _, ok = data["_ns"]; ok { ns = data["_ns"].(string) ctx, err = appengine.Namespace(ctx, ns) if err != nil { return err } } switch keyval.(type) { case int64: key = datastore.NewKey(ctx, kind, "", keyval.(int64), pkey) case string: key = datastore.NewKey(ctx, kind, keyval.(string), 0, pkey) default: return fmt.Errorf("Invalid `_key` type.") } if _, err := datastore.Put(ctx, key, JsonSaver(data)); err != nil { return err } // Check the data is actually stored. if err := wcg.RetryUntil(func() error { var v JsonSaver if err := datastore.Get(ctx, key, &v); err != nil { return fmt.Errorf( "fixture is not synched on '%s:[%s]': internal error?(%v) on ", kind, keyval, err, ) } return nil }, 5*time.Second, 500*time.Millisecond); err != nil { return err } logger.Debug("[Fixture] %s%s -- %v", ns, key, data) for _, v := range data { // Child object if child, ok := v.(map[string]interface{}); ok { if err := loadJsonToDatastore(ctx, key, child, logger); err != nil { return err } continue } // Array if children, ok := v.([]interface{}); ok { for _, child := range children { if c, ok := child.(map[string]interface{}); ok { if err := loadJsonToDatastore(ctx, key, c, logger); err != nil { return err } } } continue } } return nil }