Example #1
0
// Diff two objects, and produce an RFC 6902 JSON Patch.
func NewJSONPatch(a interface{}, b interface{}) (jsonpatch.JSONPatch, locale.Error) {
	// convert a to json
	aBytes, uerr := json.Marshal(a)
	if uerr != nil {
		return nil, locale.UntranslatedError(uerr)
	}
	// convert b to json
	bBytes, uerr := json.Marshal(b)
	if uerr != nil {
		return nil, locale.UntranslatedError(uerr)
	}
	// diff them
	p, uerr := matt.CreatePatch(aBytes, bBytes)
	if uerr != nil {
		return nil, locale.UntranslatedError(uerr)
	}
	pBytes, uerr := json.Marshal(p)
	if uerr != nil {
		return nil, locale.UntranslatedError(uerr)
	}
	// return
	var ret jsonpatch.JSONPatch
	uerr = json.Unmarshal(pBytes, &ret)
	return ret, locale.UntranslatedError(uerr)
}
Example #2
0
// Patch is a method on an application which will modify an existing Application.
func (a *Application) Patch(patchedApplication *Application) (*Application, *http.Response, []error) {
	o, err := json.Marshal(a)
	if err != nil {
		return nil, nil, []error{err}
	}

	p, err := json.Marshal(patchedApplication)
	if err != nil {
		return nil, nil, []error{err}
	}

	patch, err := jsonpatch.CreatePatch([]byte(o), []byte(p))
	if err != nil {
		fmt.Printf("Error creating JSON patch:%v", err)
		return nil, nil, []error{err}
	}

	patchBytes, err := json.Marshal(patch)
	if err != nil {
		return nil, nil, []error{err}
	}
	k := kumoru.New()

	k.Logger.Debugf("Patch string: %s", patchBytes)

	k.Patch(fmt.Sprintf("%s/v1/applications/%s", k.EndPoint.Application, a.UUID))
	k.TargetType = "json-patch+json"
	k.RawString = string(string(patchBytes))
	k.SignRequest(true)

	resp, body, errs := k.End()

	if len(errs) > 0 {
		return a, resp, errs
	}

	if resp.StatusCode >= 400 {
		errs = append(errs, fmt.Errorf("%s", resp.Status))
	}

	pApp := Application{}
	err = json.Unmarshal([]byte(body), &pApp)

	if err != nil {
		errs = append(errs, err)
		return a, resp, errs
	}

	return &pApp, resp, nil
}
Example #3
0
//called by realtime.flusher ONLY!
func (o *Object) computeUpdate() bool {
	//ensure only 1 update computation at a time
	o.mut.Lock()
	defer o.mut.Unlock()
	if o.checked {
		return false
	}
	//mark
	o.checked = true
	newBytes, err := json.Marshal(o.value)
	if err != nil {
		log.Printf("go-realtime: %s: marshal failed: %s", o.key, err)
		return false
	}
	//calculate change set
	ops, _ := jsonpatch.CreatePatch(o.bytes, newBytes)
	if len(o.bytes) > 0 && len(ops) == 0 {
		return false
	}
	delta, _ := json.Marshal(ops)
	prev := o.version
	o.version++
	//send this new change to each subscriber
	for _, u := range o.subscribers {
		update := &update{
			Key:     o.key,
			Version: o.version,
		}
		u.mut.Lock()
		//choose optimal update (send the smallest)
		if u.versions[o.key] == prev && len(o.bytes) > 0 && len(delta) < len(o.bytes) {
			update.Delta = true
			update.Data = delta
		} else {
			update.Delta = false
			update.Data = newBytes
		}
		//insert pending update
		u.pending = append(u.pending, update)
		//user now has this version
		u.versions[o.key] = o.version
		u.mut.Unlock()
	}
	o.bytes = newBytes
	return true
}