Example #1
0
// AppEngineLogHandler sends logs to AppEngine.
// The record must contain the appengine request context.
func AppEngineLogHandler() log15.Handler {
	logFormat := log15.JsonFormat()
	return log15.FuncHandler(func(r *log15.Record) error {
		var c appengine.Context
		index := 0
		for i, e := range r.Ctx {
			if ct, ok := e.(appengine.Context); ok {
				c = ct
				index = i
				break
			}
		}
		if c == nil {
			// not in the context of a request
			return nil
		}
		r.Ctx = append(r.Ctx[:index-1], r.Ctx[index+1:]...)
		log := string(logFormat.Format(r))
		switch r.Lvl {
		case log15.LvlCrit:
			c.Criticalf(log)
		case log15.LvlError:
			c.Errorf(log)
		case log15.LvlWarn:
			c.Warningf(log)
		case log15.LvlInfo:
			c.Infof(log)
		case log15.LvlDebug:
			c.Debugf(log)
		}
		return nil
	})
}
Example #2
0
func webuserOK(c appengine.Context, w http.ResponseWriter, r *http.Request) bool {
	if !userauthenticated(c) {
		url, err := user.LoginURL(c, r.URL.String())
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return false
		}
		w.Header().Set("Location", url)
		w.WriteHeader(http.StatusFound)
		return false
	}
	u := user.Current(c)
	authzed, err := userauthorized(c, u.Email)
	if err != nil {
		c.Errorf("authorization error: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return false
	}
	if !authzed {
		c.Warningf("authorization failure: %v", u.Email)
		w.WriteHeader(http.StatusForbidden)
		err = templates.ExecuteTemplate(w, "unauthorized.html", nil)
		if err != nil {
			c.Errorf("unauthorized user and got err on template: %v", err)
		}
		return false
	}
	return true
}
Example #3
0
func getCached(c appengine.Context, key string, missing func(appengine.Context, string) (*bytes.Buffer, error)) (*memcache.Item, error) {

	item, err := memcache.Get(c, key)

	if err == memcache.ErrCacheMiss {
		c.Infof("item not in the cache: %v", key)

		result, err := missing(c, key)

		if err != nil {
			return nil, err
		}

		item = &memcache.Item{
			Key:   key,
			Value: result.Bytes(),
		}

		if err := memcache.Add(c, item); err == memcache.ErrNotStored {
			c.Warningf("item with key %q already exists", item.Key)
		} else if err != nil {
			return item, err
		}
	} else if err != nil {
		return item, err
	} else {
		c.Infof("Cache hit: %v", key)
	}

	return item, nil
}
Example #4
0
// CacheAccount puts the specified Account into the cache (memcache).
func CacheAccount(c appengine.Context, acc *ds.Account) {
	mk := prefixAccForUID + acc.UserID

	if err := memcache.Set(c, &memcache.Item{Key: mk, Value: acc.Encode(), Expiration: cachedAccExpiration}); err != nil {
		c.Warningf("Failed to set %s in memcache: %v", mk, err)
	}
}
Example #5
0
func runFunc(c appengine.Context, w http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	var inv invocation
	if err := gob.NewDecoder(req.Body).Decode(&inv); err != nil {
		c.Errorf("delay: failed decoding task payload: %v", err)
		c.Warningf("delay: dropping task")
		return
	}

	f := funcs[inv.Key]
	if f == nil {
		c.Errorf("delay: no func with key %q found", inv.Key)
		c.Warningf("delay: dropping task")
		return
	}

	// TODO: This is broken for variadic functions.
	ft := f.fv.Type()
	in := make([]reflect.Value, ft.NumIn())
	in[0] = reflect.ValueOf(c)
	for i := 1; i < len(in); i++ {
		in[i] = reflect.ValueOf(inv.Args[i-1])
	}
	out := f.fv.Call(in)

	if n := ft.NumOut(); n > 0 && ft.Out(n-1) == osErrorType {
		if errv := out[n-1]; !errv.IsNil() {
			c.Errorf("delay: func failed (will retry): %v", errv.Interface())
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
	}
}
Example #6
0
// CacheDevice puts the specified Device into the cache (memcache).
func CacheDevice(c appengine.Context, dev *ds.Device) {
	mk := prefixDevForRandID + dev.RandID

	if err := memcache.Set(c, &memcache.Item{Key: mk, Value: dev.Encode()}); err != nil {
		c.Warningf("Failed to set %s in memcache: %v", mk, err)
	}
}
Example #7
0
// ClearDeviceForRandID clears the cached Device for the specified RandID.
func ClearDeviceForRandID(c appengine.Context, RandID string) {
	mk := prefixDevForRandID + RandID

	if err := memcache.Delete(c, mk); err != nil {
		c.Warningf("Failed to delete %s from memcache: %v", mk, err)
	}
}
Example #8
0
// locateFavIconURL attempts to determine the "favicon" URL for a particular
// site URL. It does this by checking the source document for explicit icon
// directives (in the LINK tags), as well as by attempting to fetch favicon.ico
func locateFavIconURL(context appengine.Context, feedHomeURL string) (string, error) {
	if feedHomeURL != "" {
		// Attempt to extract the favicon from the source document
		if favIconURL, err := extractFavIconURL(context, feedHomeURL); err != nil {
			context.Warningf("FavIcon extraction failed for %s: %s", feedHomeURL, err)
		} else if favIconURL != "" {
			if contains, err := containsFavIcon(context, favIconURL); err != nil {
				context.Warningf("FavIcon lookup failed for %s: %s", feedHomeURL, err)
			} else if contains {
				return favIconURL, nil
			}
		}

		// If that fails, try the usual location (/favicon.ico)
		if url, err := url.Parse(feedHomeURL); err != nil {
			return "", err
		} else {
			attemptURL := fmt.Sprintf("%s://%s/favicon.ico", url.Scheme, url.Host)
			if contains, err := containsFavIcon(context, attemptURL); err != nil {
				return "", err
			} else if contains {
				return attemptURL, nil
			}
		}
	}

	return "", nil
}
Example #9
0
func EditBlogCube(model *M.BlogCube, c appengine.Context) (err error) {
	key, entity := dsHelper.Model2Entity(model)
	blogCubeEntity := entity.(M.BlogCubeEntity)
	c.Warningf("The entity is %v", blogCubeEntity)
	_, err = datastore.Put(c, key, &blogCubeEntity)
	return err
}
Example #10
0
File: log.go Project: icub3d/gorca
// Log is a helper function that logs the given message to appenging
// with the given priority. Accepted priorities are "debug", "info",
// "warn", "error", and "crit". Other values default to "error".
func Log(c appengine.Context, r *http.Request, priority string,
	message string, params ...interface{}) {

	message = fmt.Sprintf("[%s] [%s] [%s]: %s", r.RemoteAddr, r.Method,
		r.URL, message)

	switch priority {
	case "debug":
		c.Debugf(message, params...)

	case "info":
		c.Infof(message, params...)

	case "warn":
		c.Warningf(message, params...)

	case "error":
		c.Errorf(message, params...)

	case "crit":
		c.Criticalf(message, params...)

	default:
		c.Errorf(message, params...)
	}
}
Example #11
0
func TriggerBatchProcessing(c appengine.Context, article ArticleId) error {
	// Instead of submitting a task to match incoming bids, resulting in one task per bid,
	// we collect bids for up to two seconds and batch-process them afterwards.
	semaphoreKey := "semaphore-" + string(article)
	if semaphore, err := memcache.Increment(c, semaphoreKey, 1, 0); err != nil {
		return err
	} else if semaphore >= 2 {
		c.Infof("Batch processing already triggered for article %v", article)
		memcache.IncrementExisting(c, semaphoreKey, -1)
		return nil
	} else {
		time.Sleep(1 * time.Second)
		c.Infof("Starting batch processing...")
		memcache.IncrementExisting(c, semaphoreKey, -1)
		time_before := time.Now()
		matchingErr := MatchIncomingBids(c, article)
		time_after := time.Now()
		duration := time_after.Sub(time_before)
		if duration > 1000*time.Millisecond {
			c.Errorf("Batch processing finished after %v. Limit exceeded!", duration)
		} else if duration > 500*time.Millisecond {
			c.Warningf("Batch processing finished after %v. Limit in danger.", duration)
		} else {
			c.Infof("Batch processing finished after %v.", duration)
		}
		return matchingErr
	}
}
Example #12
0
func storeStatsObject(c appengine.Context, st Stats, uuid string) error {
	cherr := make(chan error)

	oldSize := len(st.Data)
	if err := st.compress(); err != nil {
		return err
	}
	c.Infof("Compressed stat data from %v -> %v", oldSize, len(st.Data))

	k, err := datastore.Put(c,
		datastore.NewIncompleteKey(c, "Stats", nil), &st)
	if err != nil {
		c.Warningf("Error storing stats item:  %v", err)
		return err
	}

	go func() {
		err := couchit(c, k, nil)
		if err != nil {
			c.Errorf("Error queuing store of stats item:  %v", err)
		}
		cherr <- err
	}()

	go func() {
		err := updateUnique(c, k, uuid)
		if err != nil {
			c.Errorf("Error queueing update unique:  %v", err)
		}
		cherr <- err
	}()

	return anyErr(<-cherr, <-cherr)
}
Example #13
0
func ParseFeed(c appengine.Context, contentType, origUrl, fetchUrl string, body []byte) (*Feed, []*Story, error) {
	cr := defaultCharsetReader
	if !bytes.EqualFold(body[:len(xml.Header)], []byte(xml.Header)) {
		enc, err := encodingReader(body, contentType)
		if err != nil {
			return nil, nil, err
		}
		if enc != encoding.Nop {
			cr = nilCharsetReader
			body, err = ioutil.ReadAll(transform.NewReader(bytes.NewReader(body), enc.NewDecoder()))
			if err != nil {
				return nil, nil, err
			}
		}
	}
	var feed *Feed
	var stories []*Story
	var atomerr, rsserr, rdferr error
	feed, stories, atomerr = parseAtom(c, body, cr)
	if feed == nil {
		feed, stories, rsserr = parseRSS(c, body, cr)
	}
	if feed == nil {
		feed, stories, rdferr = parseRDF(c, body, cr)
	}
	if feed == nil {
		c.Warningf("atom parse error: %s", atomerr.Error())
		c.Warningf("xml parse error: %s", rsserr.Error())
		c.Warningf("rdf parse error: %s", rdferr.Error())
		return nil, nil, fmt.Errorf("Could not parse feed data")
	}
	feed.Url = origUrl
	return parseFix(c, feed, stories, fetchUrl)
}
Example #14
0
func AddBlogCube(model *M.BlogCube, c appengine.Context) (err error) {
	c.Warningf("addBlogCube function")
	entity := &(M.BlogCubeEntity{})
	entity.BlogName = model.BlogName
	entityName := "BlogCubeEntity"
	_, err = datastore.Put(c, datastore.NewIncompleteKey(c, entityName, nil), entity)
	return err
}
Example #15
0
func (appUser *AppUser) DSKeyID(c appengine.Context) (string, error) {
	if appUser.ID == "" {
		c.Warningf("Attempted to create an AppUser entity key with no ID!")
		return "", errors.New("AppUser has no ID!")
	}

	return "user:" + appUser.ID, nil
}
Example #16
0
func SetProperty(c appengine.Context, ref ArticleRef, propertyName string, propertyValue bool) ([]string, error) {
	articleKey, err := ref.key(c)
	if err != nil {
		return nil, err
	}

	article := new(Article)
	if err := datastore.Get(c, articleKey, article); err != nil && !IsFieldMismatch(err) {
		return nil, err
	}

	if propertyValue != article.HasProperty(propertyName) {
		wasUnread := article.IsUnread()
		wasLiked := article.IsLiked()
		unreadDelta := 0

		article.SetProperty(propertyName, propertyValue)

		// Update unread counts if necessary
		if wasUnread != article.IsUnread() {
			if wasUnread {
				unreadDelta = -1
			} else {
				unreadDelta = 1
			}
		}

		if _, err := datastore.Put(c, articleKey, article); err != nil {
			return nil, err
		}

		if wasLiked != article.IsLiked() {
			if wasLiked {
				article.updateLikeCount(c, -1)
			} else {
				article.updateLikeCount(c, 1)
			}
		}

		if unreadDelta != 0 {
			// Update unread counts - not critical
			subscriptionKey := articleKey.Parent()
			subscription := new(Subscription)

			if err := datastore.Get(c, subscriptionKey, subscription); err != nil {
				c.Warningf("Unread count update failed: subscription read error (%s)", err)
			} else if subscription.UnreadCount+unreadDelta >= 0 {
				subscription.UnreadCount += unreadDelta
				if _, err := datastore.Put(c, subscriptionKey, subscription); err != nil {
					c.Warningf("Unread count update failed: subscription write error (%s)", err)
				}
			}
		}
	}

	return article.Properties, nil
}
Example #17
0
func parseRSS(c appengine.Context, body []byte, charsetReader func(string, io.Reader) (io.Reader, error)) (*Feed, []*Story, error) {
	var f Feed
	var s []*Story
	r := rss.Rss{}
	d := xml.NewDecoder(bytes.NewReader(body))
	d.CharsetReader = charsetReader
	d.DefaultSpace = "DefaultSpace"
	if err := d.Decode(&r); err != nil {
		return nil, nil, err
	}
	f.Title = r.Title
	if t, err := parseDate(c, &f, r.LastBuildDate, r.PubDate); err == nil {
		f.Updated = t
	} else {
		c.Warningf("no rss feed date: %v", f.Link)
	}
	f.Link = r.BaseLink()
	f.Hub = r.Hub()

	for _, i := range r.Items {
		st := Story{
			Link:   i.Link,
			Author: i.Author,
		}
		if i.Content != "" {
			st.content = i.Content
		} else if i.Description != "" {
			st.content = i.Description
		}
		if i.Title != "" {
			st.Title = i.Title
		} else if i.Description != "" {
			st.Title = i.Description
		}
		if st.content == st.Title {
			st.Title = ""
		}
		st.Title = textTitle(st.Title)
		if i.Guid != nil {
			st.Id = i.Guid.Guid
		}
		if i.Enclosure != nil && strings.HasPrefix(i.Enclosure.Type, "audio/") {
			st.MediaContent = i.Enclosure.Url
		} else if i.Media != nil && strings.HasPrefix(i.Media.Type, "audio/") {
			st.MediaContent = i.Media.URL
		}
		if t, err := parseDate(c, &f, i.PubDate, i.Date, i.Published); err == nil {
			st.Published = t
			st.Updated = t
		}

		s = append(s, &st)
	}
	return &f, s, nil
}
Example #18
0
func storeInCouch(c appengine.Context, ob map[string]interface{}, k string) (rv string, err error) {
	// log.Printf("Storing in couchdb: %+v", ob)

	if baseDBURL == "" {
		c.Warningf("CouchDB is not configured.  Deferring")
		return "", errors.New("not configured")
	}

	dbname := miscDB
	switch {
	case strings.HasPrefix(k, "stats_"):
		dbname = statsDB
	case strings.HasPrefix(k, "unique_"):
		dbname = uniqueDB
	}

	js, err := json.Marshal(ob)
	if err != nil {
		return "", err
	}

	req, err := http.NewRequest("PUT", baseDBURL+dbname+"/"+k, bytes.NewReader(js))
	if err != nil {
		return "", err
	}

	req.Header.Set("Authorization", authHeader)
	req.Header.Set("Content-Type", "application/json")

	t := &urlfetch.Transport{Context: c}
	resp, err := t.RoundTrip(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	switch {
	case resp.StatusCode == 409:
		c.Infof("Conflict updating %s", k)
	case resp.StatusCode >= 200 && resp.StatusCode < 300:
		c.Debugf("Updated couch with %v", resp.StatusCode)

		withRev := struct {
			Rev string `json:"rev"`
		}{}
		d := json.NewDecoder(resp.Body)
		err = d.Decode(&withRev)
		rv = withRev.Rev
	default:
		return "", fmt.Errorf("Failed to update couch:  %v", resp.Status)
	}

	return
}
Example #19
0
func cacheJson(c appengine.Context, id int64, data []byte) error {
	memId := jsonMemId(id)
	item := &memcache.Item{
		Key:   memId,
		Value: data,
	}
	err := memcache.Set(c, item)
	if err != nil {
		c.Warningf("can't write %v to memcache: %v", memId, err)
	}
	return err
}
Example #20
0
func retrieveAuth(context appengine.Context) *Auth {
	//  First, check memcache
	auth := Auth{}
	_, err := memcache.Gob.Get(context, "rackspace-auth", &auth)
	if err == memcache.ErrCacheMiss {
		return newAuth(context)
	} else if err != nil {
		context.Warningf("error retrieving item %v", err)
		return newAuth(context)
	}
	return &auth
}
Example #21
0
func (f Feed) Subscribe(c appengine.Context) {
	if !f.IsSubscribed() {
		t := taskqueue.NewPOSTTask(routeUrl("subscribe-feed"), url.Values{
			"feed": {f.Url},
		})
		if _, err := taskqueue.Add(c, t, "update-manual"); err != nil {
			c.Errorf("taskqueue error: %v", err.Error())
		} else {
			c.Warningf("subscribe feed: %v", f.Url)
		}
	}
}
Example #22
0
// cacheDevListForAccKey puts the specified Device list into the cache (memcache).
func cacheDevListForAccKey(c appengine.Context, accKey *datastore.Key, devices []*ds.Device) {
	mk := prefixDevListForAccKey + strconv.FormatInt(accKey.IntID(), 10)

	data, err := json.Marshal(devices) // This can't really fail
	if err != nil {
		c.Errorf("Failed to encode device list to JSON: %v", err)
	}

	if err = memcache.Set(c, &memcache.Item{Key: mk, Value: data}); err != nil {
		c.Warningf("Failed to set %s in memcache: %v", mk, err)
	}
}
Example #23
0
func Read(c appengine.Context, w http.ResponseWriter, r *http.Request) error {
	w.Header().Set("Content-Type", "application/xhtml+xml; charset=UTF-8")

	var id string
	if strings.HasPrefix(r.URL.Path, "/read/") {
		id = r.URL.Path[len("/read/"):]
	} else {
		return NotFound(r.URL.Path)
	}

	type metadata struct {
		Label string
		Value string
	}
	type renderdata struct {
		Title string
		Meta  []metadata
		HTML  string
	}

	var data renderdata

	s, err := GetStory(c, id)
	if err != nil {
		return err
	}

	data.Title = html.EscapeString(s.Title)

	for name, prop := range s.Meta {
		if len(name) == 0 || len(prop.Name) == 0 {
			c.Warningf("Zero-length property name?")
			continue
		}
		data.Meta = append(data.Meta, metadata{
			Label: html.EscapeString(strings.ToUpper(prop.Name[:1]) + prop.Name[1:]),
			Value: html.EscapeString(prop.Value),
		})
	}

	if node, err := fictex.ParseBytes(s.Source); err == nil {
		b := new(bytes.Buffer)
		if err := fictex.HTMLRenderer.Render(b, node); err == nil {
			data.HTML = b.String()
		}
	} else {
		data.HTML = html.EscapeString(fmt.Sprintf("Error: %s", err))
	}

	return templates.ExecuteTemplate(w, "render.html", data)
}
Example #24
0
// Add attempts to write a new Student entity; it will not overwrite
// any existing Students. Returns ErrClassFull if the class is full as
// of the given date. The number of students "currently registered"
// for a class is the number of session-registered students plus any
// future drop ins. This may be smaller than the number of students
// registered on a particular day, and so may prevent drop-ins which
// may otherwise have succeeded. In other words, a student can only
// drop in if we can prove that there is room for them to register for
// the rest of the session.
func (s *Student) Add(c appengine.Context, asOf time.Time) error {
	key := s.key(c)
	var txnErr error
	for i := 0; i < 25; i++ {
		txnErr = datastore.RunInTransaction(c, func(c appengine.Context) error {
			old := &Student{}
			switch err := datastore.Get(c, key, old); err {
			case datastore.ErrNoSuchEntity:
				break
			case nil:
				if old.DropIn && old.Date.Before(asOf) {
					// Old registration is an expired drop-in. Allow re-registering.
					break
				}
				// Old registration is still active; do nothing.
				c.Warningf("Attempted duplicate registration of %q in %d", s.ID, s.ClassID)
				return nil
			default:
				return fmt.Errorf("students: failed to look up existing student: %s", err)
			}
			class, err := classes.ClassWithID(c, s.ClassID)
			if err != nil {
				return err
			}
			in := In(c, class, asOf)
			if int32(len(in)) >= class.Capacity {
				return ErrClassIsFull
			}
			if err := class.Update(c); err != nil {
				return fmt.Errorf("students: failed to update class: %s", err)
			}
			if _, err := datastore.Put(c, key, s); err != nil {
				return fmt.Errorf("students: failed to write student: %s", err)
			}
			return nil
		}, nil)
		if txnErr != datastore.ErrConcurrentTransaction {
			break
		}
	}
	switch txnErr {
	case nil:
		return nil
	case datastore.ErrConcurrentTransaction:
		return fmt.Errorf("students: too many concurrent updates to class %d", s.ClassID)
	default:
		return txnErr
	}
}
Example #25
0
func writeLogMessage(c appengine.Context, level logLevel, msg string) {
	const fmt = "%s"
	switch level {
	case levelDebug:
		c.Debugf(fmt, msg)
	case levelWarning:
		c.Warningf(fmt, msg)
	case levelError:
		c.Errorf(fmt, msg)
	case levelCritical:
		c.Criticalf(fmt, msg)
	default:
		c.Infof(fmt, msg)
	}
}
Example #26
0
func postToCouch(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	err := postToCouchCommon(c, r.FormValue("key"), r.FormValue("isnew") == "true")
	if err != nil {
		c.Errorf("Error posting to couchdb %q: %v", r.FormValue("key"), err)
		http.Error(w, err.Error(), 500)
		return
	}

	if err != nil {
		c.Warningf("Could not couch %v: %v", r.FormValue("key"), err)
		http.Error(w, err.Error(), 503)
	} else {
		w.WriteHeader(201)
	}
}
Example #27
0
func (self *AppCubeFilter) Filte(w http.ResponseWriter, r *http.Request, c appengine.Context) bool {
	c.Warningf("app cube filte")
	// (self.App.GetAppCube())["BlogName"] = "Core"
	if _, ok := (self.App.GetAppCube())["BlogCube"]; !ok {
		cube, _ := ds.GetBlogCube(c)
		if cube == nil {
			cube = &M.BlogCube{}
			cube.BlogName = "Blog"
			cube.NoRight = false
			ds.AddBlogCube(cube, c)
		}
		self.App.GetAppCube()["BlogCube"] = cube
	}

	return true
}
Example #28
0
func Unsubscribe(c appengine.Context, ref SubscriptionRef) error {
	subscriptionKey, err := ref.key(c)
	if err != nil {
		return err
	}

	if err := datastore.Delete(c, subscriptionKey); err != nil {
		return err
	}

	if err := updateSubscriberCount(c, ref.SubscriptionID, -1); err != nil {
		c.Warningf("Error decrementing subscriber count: %s", err)
	}

	return nil
}
Example #29
0
// DELETE ./groups/xxx", xxx: Group name
// Header {"Instance-Id":"..."}
// Success returns 204 No Content
// Failure returns 400 Bad Request, 403 Forbidden, 500 Internal Server Error
func LeaveGroup(rw http.ResponseWriter, req *http.Request) {
	// Appengine
	var c appengine.Context = appengine.NewContext(req)
	// Result, 0: success, 1: failed
	var r int = http.StatusNoContent
	// Sender instance ID
	var instanceId string
	// Group name to leave
	var groupName string
	// Function to write response header
	defer func() {
		if r == http.StatusNoContent {
			// Return status. WriteHeader() must be called before call to Write
			rw.WriteHeader(r)
		} else {
			http.Error(rw, http.StatusText(r), r)
		}
	}()

	// Get instance ID from header
	instanceId = req.Header.Get("Instance-Id")
	if instanceId == "" {
		c.Warningf("Missing instance ID. Ignore the request.")
		r = http.StatusBadRequest
		return
	}

	// Get group name from URL
	var tokens []string
	tokens = strings.Split(req.URL.Path, "/")
	for i, v := range tokens {
		if v == "groups" && i+1 < len(tokens) {
			groupName = tokens[i+1]
			break
		}
	}
	if groupName == "" {
		c.Warningf("Missing group name. Ignore the request.")
		r = http.StatusBadRequest
		return
	}

	// Vernon debug
	c.Debugf("User %s is going to leave group %s", instanceId, groupName)

	r = leaveGroup(c, instanceId, groupName)
}
Example #30
0
func runFunc(c appengine.Context, w http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	var inv invocation
	if err := gob.NewDecoder(req.Body).Decode(&inv); err != nil {
		c.Errorf("delay: failed decoding task payload: %v", err)
		c.Warningf("delay: dropping task")
		return
	}

	f := funcs[inv.Key]
	if f == nil {
		c.Errorf("delay: no func with key %q found", inv.Key)
		c.Warningf("delay: dropping task")
		return
	}

	ft := f.fv.Type()
	in := []reflect.Value{reflect.ValueOf(c)}
	for _, arg := range inv.Args {
		var v reflect.Value
		if arg != nil {
			v = reflect.ValueOf(arg)
		} else {
			// Task was passed a nil argument, so we must construct
			// the zero value for the argument here.
			n := len(in) // we're constructing the nth argument
			var at reflect.Type
			if !ft.IsVariadic() || n < ft.NumIn()-1 {
				at = ft.In(n)
			} else {
				at = ft.In(ft.NumIn() - 1).Elem()
			}
			v = reflect.Zero(at)
		}
		in = append(in, v)
	}
	out := f.fv.Call(in)

	if n := ft.NumOut(); n > 0 && ft.Out(n-1) == osErrorType {
		if errv := out[n-1]; !errv.IsNil() {
			c.Errorf("delay: func failed (will retry): %v", errv.Interface())
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
	}
}