code: func fetchChangesCached(c context.Context, b *buildbot.Build) error {
  	report := func(err error, msg string) {
  		logging.WithError(err).Errorf(c, "build %q change memcaching: %s", b.ID(), msg)
  	}
  
  	cache := memcache.NewItem(c, "buildbot_changes/"+b.ID().String())
  	if err := memcache.Get(c, cache); err == nil {
  		err := json.Unmarshal(cache.Value(), &b.Sourcestamp.Changes)
  		if err == nil {
  			return nil
  		}
  		b.Sourcestamp.Changes = nil
  		report(err, "failed to unmarshal memcached changes")
  	} else if err != memcache.ErrCacheMiss {
  		report(err, "failed to load")
  	}
  
  	if err := fetchChanges(c, b); err != nil {
  		return err
  	}
  
  	marshaled, err := json.Marshal(b.Sourcestamp.Changes)
  	if err != nil {
  		return err
  	}
  	if len(marshaled) > 1<<20 {
  		report(nil, "cannot save > 1MB")
  	} else {
  		cache.SetValue(marshaled)
  		if err := memcache.Set(c, cache); err != nil {
  			report(err, "failed to save")
  		}
  	}
  	return nil
  }
docs: // fetchChangesCached is same as fetchChanges, but with memcaching.