Beispiel #1
0
func TestPutPropertyLoadSaver(t *testing.T) {
	c, closeFunc := NewContext(t)
	defer closeFunc()

	type testEntity struct {
		IntVal int
	}

	te := &testEntity{2}
	pl, err := datastore.SaveStruct(te)
	if err != nil {
		t.Fatal(err)
	}

	keys := []*datastore.Key{datastore.NewKey(c, "Test", "", 1, nil)}

	pls := datastore.PropertyList(pl)
	if _, err := nds.PutMulti(c, keys,
		[]datastore.PropertyLoadSaver{&pls}); err != nil {
		t.Fatal(err)
	}

	getPl := datastore.PropertyList{}
	if err := nds.GetMulti(c,
		keys, []datastore.PropertyLoadSaver{&getPl}); err != nil {
		t.Fatal(err)
	}
	getTe := &testEntity{}
	if err := datastore.LoadStruct(getTe, getPl); err != nil {
		t.Fatal(err)
	}
	if te.IntVal != getTe.IntVal {
		t.Fatal("expected same IntVal", getTe.IntVal)
	}
}
Beispiel #2
0
// retrieve obtains the application configuration as a datastore.PropertyList.
func retrieve(ctx context.Context) (datastore.PropertyList, error) {

	p := datastore.PropertyList(make([]datastore.Property, 0, 8))
	key := datastore.NewKey(ctx, Entity, Entity, 0, nil)
	err := nds.Get(ctx, key, &p)
	return p, err

}
Beispiel #3
0
// Save changes the application configuration to
// the values in conf. All HTTP requests subsequent to this one
// are guaranteed to use the new values in their configuration.
//
// Note that subsequent calls to Get with the same request context
// will continue to retrieve the old version of the configuration.
//
// As a special case, calling Save with a *config.Config will replace
// the entire contents of the configuration with the contents of Config.
func Save(ctx context.Context, conf interface{}) error {

	if typedConfig, ok := conf.(*Config); ok {
		pl := datastore.PropertyList(*typedConfig)
		replaceKey := datastore.NewKey(ctx, Entity, Entity, 0, nil)
		_, replaceErr := nds.Put(ctx, replaceKey, &pl)
		return replaceErr
	}

	return datastore.RunInTransaction(ctx, func(txCtx context.Context) error {

		props := datastore.PropertyList{}

		key := datastore.NewKey(txCtx, Entity, Entity, 0, nil)
		if err := nds.Get(txCtx, key, &props); err != nil && err != datastore.ErrNoSuchEntity {
			return err
		}

		// merge existing config with the new values
		if newProps, err := datastore.SaveStruct(conf); err != nil {
			return err
		} else {

			for _, newProp := range newProps {
				newProp.NoIndex = true
				replacing := false
				for _, prop := range props {
					// make sure NoIndex is set
					prop.NoIndex = true
					if prop.Name == newProp.Name {
						replacing = true
						prop.Value = newProp.Value
						break
					}
				}
				if !replacing {
					// append
					props = append(props, newProp)
				}

			}

		}

		_, err := nds.Put(txCtx, key, &props)
		return err

	}, nil)

}
Beispiel #4
0
	// memcacheLockTime is the maximum length of time a memcache lock will be
	// held for. 32 seconds is chosen as 30 seconds is the maximum amount of
	// time an underlying datastore call will retry even if the API reports a
	// success to the user.
	memcacheLockTime = 32 * time.Second

	// memcacheMaxKeySize is the maximum size a memcache item key can be. Keys
	// greater than this size are automatically hashed to a smaller size.
	memcacheMaxKeySize = 250
)

var (
	typeOfPropertyLoadSaver = reflect.TypeOf(
		(*datastore.PropertyLoadSaver)(nil)).Elem()
	typeOfPropertyList = reflect.TypeOf(datastore.PropertyList(nil))
)

// The variables in this block are here so that we can test all error code
// paths by substituting them with error producing ones.
var (
	datastoreDeleteMulti = datastore.DeleteMulti
	datastoreGetMulti    = datastore.GetMulti
	datastorePutMulti    = datastore.PutMulti

	memcacheAddMulti            = memcache.AddMulti
	memcacheCompareAndSwapMulti = memcache.CompareAndSwapMulti
	memcacheDeleteMulti         = memcache.DeleteMulti
	memcacheGetMulti            = memcache.GetMulti
	memcacheSetMulti            = memcache.SetMulti