예제 #1
0
/* logic:
   input: key, *struct

   a) Check if key has Id; yes/no
       no) INCR k:count
           set value as Id in struct

   b) Parse struct; returns [field, value, field, value, ...], [hashField, ...].
      the hashField slice contains any optional properties which should be applied
      to before or after setting the struct in Redis (uniquity, index).

   c) Check unique fields and set unique fields

   d) Add the actual data from struct to a redis hash

   e) Add optional indexes

   f) if c, d, e did raise an error we need to cleanup the things
      we changed in the database.
*/
func Put(db *redis.Client, k *Key, s interface{}) (*Key, error) {
	mon := monitoring.BeginMeasuring("database:put")
	defer mon.EndMeasuring()
	prep := new(prepare)
	prep.key = k

	e := setId(db, s, prep)

	if e != nil {
		return nil, e
	}

	e = parseStruct(db, s, prep)

	if e != nil {
		return nil, e
	}

	for _, o := range prep.unique {
		uk := k.Unique(o.name, fmt.Sprintf("%v", *o.value))
		var reply *redis.Reply
		// TODO: Watch key
		reply, e = db.Call("GET", uk)

		if e != nil {
			goto Error
		}

		if !reply.Nil() && reply.Elem.Int64() != k.Id() {
			e = newUniqueError(o.name, *o.value)
			goto Error
		}

		reply, e = db.Call("SET", uk, k.Id())

		if e != nil {
			goto Error
		}

		prep.dirty = append(prep.dirty, uk)
	}

	_, e = db.Call(append([]interface{}{"HMSET", k.String()}, prep.args...)...)

	for _, o := range prep.index {
		ik := fmt.Sprintf("%v", *o.value)
		_, e = db.Call("SET", k.Index(o.name, ik), k.Id())

		if e != nil {
			goto Error
		}

		prep.dirty = append(prep.dirty, ik)
	}

	return k, e
Error:
	cleanup(db, prep)
	return nil, e
}
예제 #2
0
func Get(db *redis.Client, k *Key, s interface{}) error {
	mon := monitoring.BeginMeasuring("database:get")
	reply, e := db.Call("HGETALL", k.String())

	if e != nil {
		return e
	}

	if reply.Len() == 0 {
		return nilError
	}

	e = inflate(db, s, reply.Hash())
	mon.EndMeasuring()
	return e
}