Example #1
0
func (api *MigrationAPI) Start() error {
	runAll := delay.Func("*MigrationService.RunAll", func(ctx context.Context) error {
		return api.MigrationService.RunAll(AsSuperuser(ctx))
	})

	api.Mutations = map[string]*graphql.Field{
		"migrate": relay.MutationWithClientMutationID(relay.MutationConfig{
			Name:         "Migrate",
			InputFields:  graphql.InputObjectConfigFieldMap{},
			OutputFields: graphql.Fields{},
			MutateAndGetPayload: func(inputMap map[string]interface{}, info graphql.ResolveInfo, ctx context.Context) (map[string]interface{}, error) {
				u, err := api.UserService.FromContext(ctx)
				if err != nil {
					return nil, err
				}

				if !u.IsAdmin {
					return nil, errors.New("user must be an admin")
				}

				err = runAll.Call(ctx)
				if err != nil {
					return nil, err
				}

				return map[string]interface{}{}, nil
			},
		}),
	}

	return nil
}
Example #2
0
func init() {
	delayedGetStats = delay.Func(
		"my-favorite-dog",
		func(ctx context.Context, accessToken, username string) error {
			log.Infof(ctx, "delayedGetStats CALLED")
			api := &GithubAPI{
				ctx:         ctx,
				accessToken: accessToken,
				username:    username,
			}
			since := time.Now().Add(-time.Hour * 24 * 30)
			stats, err := api.getCommitSummaryStats(since)
			if err != nil {
				return err
			}
			log.Infof(ctx, "STATS: %v", stats)

			key := datastore.NewKey(ctx, "Stats", username, 0, nil)
			_, err = datastore.Put(ctx, key, &stats)
			if err != nil {
				return err
			}
			return nil
		},
	)
}
func init() {
	// created in init because it's called inside the function itself
	processFunc = delay.Func("process", process)

	// complete endpoint will be something like "/_ah/cron/process/logPhotos"
	cron.Get("/process/:name", processHandler)
}
func init() {
	// created in init because it's called inside the function
	processPhotosFunc = delay.Func("processPhotos", processPhotos)

	// complete endpoint will be something like "/_ah/cron/photos/log"
	cron.Get("/photos/:processor", processPhotosHandler)
}
func init() {
	reindexDelayer = delay.Func("reindex-idioms", func(c context.Context, cursorStr string) error {
		q := datastore.NewQuery("Idiom")
		if cursorStr != "" {
			log.Infof(c, "Starting at cursor %v", cursorStr)
			cursor, err := datastore.DecodeCursor(cursorStr)
			if err != nil {
				return err
			}
			q = q.Start(cursor)
		}
		iterator := q.Run(c)

		reindexedIDs := make([]int, 0, reindexBatchSize)
		defer func() {
			log.Infof(c, "Reindexed idioms %v", reindexedIDs)
		}()

		for i := 0; i < reindexBatchSize; i++ {
			var idiom Idiom
			key, err := iterator.Next(&idiom)
			if err == datastore.Done {
				log.Infof(c, "Reindexing completed.")
				return nil
			} else if err != nil {
				// ouch :(
				return err
			}

			err = indexIdiomFullText(c, &idiom, key)
			if err != nil {
				log.Errorf(c, "Reindexing full text idiom %d : %v", idiom.Id, err)
			}
			err = indexIdiomCheatsheets(c, &idiom)
			if err != nil {
				log.Errorf(c, "Reindexing cheatsheet of idiom %d : %v", idiom.Id, err)
			}

			reindexedIDs = append(reindexedIDs, idiom.Id)
		}

		cursor, err := iterator.Cursor()
		if err != nil {
			// ouch :(
			return err
		}
		log.Infof(c, "Stopping at cursor %v", cursor.String())
		reindexDelayer.Call(c, cursor.String())
		return nil
	})
}
Example #6
0
func example() {
	var ctx context.Context
	var t *taskqueue.Task
	_ = t

	// [START deferred_tasks]
	var expensiveFunc = delay.Func("some-arbitrary-key", func(ctx context.Context, a string, b int) {
		// do something expensive!
	})

	// Somewhere else
	expensiveFunc.Call(ctx, "Hello, world!", 42)
	// [END deferred_tasks]

	// [START URL_endpoints]
	t = &taskqueue.Task{Path: "/path/to/my/worker"}
	t = &taskqueue.Task{Path: "/path?a=b&c=d", Method: "GET"}
	// [END URL_endpoints]
}
Example #7
0
import (
	"net/http"
	"strconv"

	"google.golang.org/appengine/delay"
	"google.golang.org/appengine/log"

	"github.com/gorilla/mux"
	"github.com/jittuu/hivepeek/internal"

	"golang.org/x/net/context"
)

var (
	delayFetchMatchesByLeagueFunc = delay.Func("fetch-matches-by-league", delayFetchMatchesByLeague)
)

func AllMatchesByLeague(c context.Context, w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	l, err := strconv.Atoi(vars["league"])
	if err != nil {
		return err
	}
	s := vars["season"]
	db := &internal.DSContext{c}
	matches, err := db.GetAllMatchesByLeagueAndSeason(l, s)
	if err != nil {
		return err
	}
Example #8
0
package controllers

import (
	"io"
	"io/ioutil"
	"net/http"
	"net/mail"

	"golang.org/x/net/context"

	"google.golang.org/appengine/delay"
	"google.golang.org/appengine/log"
	appmail "google.golang.org/appengine/mail"
)

var echoMailFunc = delay.Func("echoMail", echoMail)

func init() {
	router.Handle("/_ah/mail/", ContextHandlerFunc(ReceiveMail))
}

func echoMail(ctx context.Context, m mail.Message) {
	from, err := m.Header.AddressList("From")
	if err != nil {
		log.Warningf(ctx, "Failed getting sender of mail: %+v", m)
		return
	}

	b, _ := ioutil.ReadAll(m.Body)

	am := &appmail.Message{
Example #9
0
func init() {
	delayedPuppy = delay.Func("delayedPuppy", runLater)
}
Example #10
0
// BuildJustinCommandHandler builds an HTTP endpoint that responds to a Justin Slack "slash command"
// - command is the expected Slack command, or empty string if we don't care
// - token is the expected Slack token, or empty string if we don't care
func BuildJustinCommandHandler(expectedCommand string, expectedToken string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		ctx := appengine.NewContext(req)

		userName := req.PostFormValue("user_name")
		token := req.PostFormValue("token")
		command := req.PostFormValue("command")
		text := req.PostFormValue("text")
		responseURL := req.PostFormValue("response_url")

		log.Debugf(ctx, `Request: userName: %s
token: %s
command: %s
text: %s
team id: %s
team domain: %s
channel id: %s
channel name: %s
user id: %s
response url: %s`, userName, token, command, text, req.PostFormValue("team_id"), req.PostFormValue("team_domain"), req.PostFormValue("channel_id"),
			req.PostFormValue("channel_name"), req.PostFormValue("user_id"), responseURL)

		// Validate if we're supposed to
		if expectedCommand != "" && command != expectedCommand {
			log.Errorf(ctx, "Forbidden - invalid command '%s'; expected '%s'", command, expectedCommand)
			http.Error(w, `"Forbidden"`, http.StatusForbidden)
			return
		}
		if expectedToken != "" && token != expectedToken {
			log.Errorf(ctx, "Forbidden - invalid token '%s'; expected '%s'", token, expectedToken)
			http.Error(w, `"Forbidden"`, http.StatusForbidden)
			return
		}

		// build the Slack response text
		response := fmt.Sprintf("Here's what I found:\n\nhttps://www.google.com/#q=%s", url.QueryEscape(strings.TrimSpace(text)))
		if strings.HasSuffix(text, "?") {
			response = fmt.Sprintf("Great question, @%s! %s", userName, response)
		} else {
			response = fmt.Sprintf("You got it, @%s! %s", userName, response)
		}

		// Create the JSON payload with the response, to send back to Slack
		respBytes, err := buildSlackJSON(ctx, response, true)
		if err != nil {
			// already logged
			http.Error(w, "Error", 500)
			return
		}

		// tell Slack to show the user's command
		w.Header().Set("Content-Type", "application/json")
		_, err = w.Write([]byte(`{"response_type": "in_channel"}`))
		if err != nil {
			log.Errorf(ctx, "Error echoing the request: %s", err)
		}

		// queue up the delayed response
		var laterFunc = delay.Func("key", func(delayCtx context.Context, x string) {
			log.Debugf(delayCtx, "Sending delayed response to Slack for request: %s", text)
			time.Sleep(500 * time.Millisecond)
			err := sendSlackJSON(delayCtx, responseURL, respBytes)
			if err != nil {
				// already logged
				return
			}
			log.Debugf(delayCtx, "Success! Response sent back to Slack: %s", respBytes)
		})
		laterFunc.Call(ctx, "")
	}
}
Example #11
0
		}
		return nil
	}, &datastore.TransactionOptions{XG: true})
	if err != nil {
		handleError(c, w, err, http.StatusInternalServerError)
		return
	}
}

var backupHTMLBlockFunc = delay.Func("backup", func(c context.Context, uuid string, blocks []*model.HTMLBlock) error {
	for i, block := range blocks {
		backupKey := model.NewHTMLBlockBackupKey(c, fmt.Sprintf("%s-%02d", uuid, i))
		var backup model.HTMLBlockBackup
		backup.HTMLBlockKey = block.Key
		backup.HTMLBlock = *block
		// without nds cache
		if _, err := datastore.Put(c, backupKey, &backup); err != nil {
			log.Errorf(c, err.Error())
			return err
		}
	}
	return nil
})

func getRequestJson(w http.ResponseWriter, r *http.Request, p interface{}) error {
	decoder := json.NewDecoder(r.Body)
	err := decoder.Decode(p)
	if err != nil {
		return err
	}

	return nil
Example #12
0
import (
	"time"

	"math/rand"
	"net/http"

	"github.com/qedus/nds"
	"golang.org/x/net/context"
	"google.golang.org/appengine"
	"google.golang.org/appengine/datastore"
	"google.golang.org/appengine/delay"
)

var (
	generateRandomFn = delay.Func("generateRandom", generateRandom)
	photographers    = []Photographer{
		{1, "Mr Canon"},
		{2, "Miss Nikon"},
		{3, "Mrs Pentax"},
		{4, "Ms Sony"},
	}
)

func init() {
	http.Handle("/_ah/warmup", http.HandlerFunc(warmupHandler))
}

func warmupHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if errTooManyItems != nil {
		// Return error *after* the restoring is done
		return historyIdiom, errTooManyItems
	}
	return historyIdiom, nil
}

// Delayers registered at init time

// TODO take real Idiom as parameter, not a Key or a pointer
var historyDelayer = delay.Func("save-history-item", func(c context.Context, idiomKey *datastore.Key) error {
	var historyItem IdiomHistory
	// TODO check Memcache first
	err := datastore.Get(c, idiomKey, &historyItem.Idiom)
	if err != nil {
		return err
	}
	historyItem.ComputeIdiomOrImplLastEditor()
	// Saves a new IdiomHistory entity. This causes no contention on the original Idiom entity.
	_, err = datastore.Put(c, newHistoryKey(c), &historyItem)
	return err
})

var indexDelayer = delay.Func("index-text-idiom", func(c context.Context, idiomKey *datastore.Key) error {
	var idiom Idiom
	// TODO check Memcache first
	err := datastore.Get(c, idiomKey, &idiom)
	if err != nil {
		return err
	}
	// Full text API causes no contention on the original Idiom entity.
	err = indexIdiomFullText(c, &idiom, idiomKey)
Example #14
0
package backoffice

import (
	"net/http"

	"github.com/jittuu/hivepeek/internal"
	"google.golang.org/appengine/delay"
	"google.golang.org/appengine/log"

	"golang.org/x/net/context"
)

var (
	delayFetchLeaguesFunc = delay.Func("fetch-leagues", delayFetchCompetitions)
)

func AllLeagues(c context.Context, w http.ResponseWriter, r *http.Request) error {
	db := &internal.DSContext{c}
	lgs, err := db.GetAllLeagues()
	if err != nil {
		return err
	}
	return internal.Json(w, lgs)
}

func FetchLeagues(c context.Context, w http.ResponseWriter, r *http.Request) error {
	err := delayFetchLeaguesFunc.Call(c)
	return err
}

func delayFetchCompetitions(c context.Context) error {
Example #15
0
package backoffice

import (
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/jittuu/hivepeek/internal"

	"golang.org/x/net/context"
	"google.golang.org/appengine/delay"
	"google.golang.org/appengine/log"
)

var (
	delayFetchTeamsFunc = delay.Func("fetch-teams-by-league", delayFetchTeams)
)

func AllTeamsByLeague(c context.Context, w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	l, err := strconv.Atoi(vars["league"])
	if err != nil {
		return err
	}
	s := vars["season"]
	db := &internal.DSContext{c}
	teams, err := db.GetAllTeamsByLeagueAndSeason(l, s)
	if err != nil {
		return err
	}