Esempio di una coda di attività Go

Questo esempio crea un'app che mostra un modulo HTML. Inserisci una stringa nella finestra di dialogo e fai clic su Add. L'app conta il numero di volte di inserire qualsiasi stringa in questo modo.

L'app esegue le seguenti operazioni:

  • Quando fai clic su Add, il modulo utilizza una richiesta HTTP POST per inviare la stringa all'app in esecuzione su App Engine. L'app raggruppa la stringa in un'attività e la invia alla coda predefinita.
  • La coda inoltra l'attività a un gestore di attività incluso, mappato all'URL /worker, che scrive in modo asincrono la stringa in un datastore.
  • L'invio di una richiesta GET HTTP mostra un elenco delle stringhe inserite e il numero di volte che haiAddeseguito ogni stringa, digitandola o selezionandolo nel menu a discesa.

Per eseguire il deployment di questa app in App Engine:

  1. Copia quanto segue in un file denominato queue.yaml. In questo modo, la frequenza di elaborazione delle attività passa da 5 al secondo (valore predefinito) a 3 al secondo.

    queue:
    - name: default
      rate: 3/s
    
  2. Nella stessa directory, copia il seguente codice in un file denominato come preferisci (che termina con .go). Si tratta del codice dell'applicazione, incluso l'handler delle attività.

    
    package counter
    
    import (
    	"html/template"
    	"net/http"
    
    	"google.golang.org/appengine"
    	"google.golang.org/appengine/datastore"
    	"google.golang.org/appengine/log"
    	"google.golang.org/appengine/taskqueue"
    )
    
    func init() {
    	http.HandleFunc("/", handler)
    	http.HandleFunc("/worker", worker)
    }
    
    type Counter struct {
    	Name  string
    	Count int
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	ctx := appengine.NewContext(r)
    	if name := r.FormValue("name"); name != "" {
    		t := taskqueue.NewPOSTTask("/worker", map[string][]string{"name": {name}})
    		if _, err := taskqueue.Add(ctx, t, ""); err != nil {
    			http.Error(w, err.Error(), http.StatusInternalServerError)
    			return
    		}
    	}
    	q := datastore.NewQuery("Counter")
    	var counters []Counter
    	if _, err := q.GetAll(ctx, &counters); err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}
    	if err := handlerTemplate.Execute(w, counters); err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}
    	// OK
    }
    
    func worker(w http.ResponseWriter, r *http.Request) {
    	ctx := appengine.NewContext(r)
    	name := r.FormValue("name")
    	key := datastore.NewKey(ctx, "Counter", name, 0, nil)
    	var counter Counter
    	if err := datastore.Get(ctx, key, &counter); err == datastore.ErrNoSuchEntity {
    		counter.Name = name
    	} else if err != nil {
    		log.Errorf(ctx, "%v", err)
    		return
    	}
    	counter.Count++
    	if _, err := datastore.Put(ctx, key, &counter); err != nil {
    		log.Errorf(ctx, "%v", err)
    	}
    }
    
    var handlerTemplate = template.Must(template.New("handler").Parse(handlerHTML))
    
    const handlerHTML = `
    {{range .}}
    <p>{{.Name}}: {{.Count}}</p>
    {{end}}
    <p>Start a new counter:</p>
    <form action="/" method="POST">
    <input type="text" name="name">
    <input type="submit" value="Add">
    </form>
    `
    
  3. Nella stessa directory, copia quanto segue in un file denominato app.yaml. In questo modo, l'applicazione viene configurata per App Engine:

    runtime: go
    api_version: go1
    
    handlers:
    - url: /worker/.*
      script: _go_app
      login: admin
    - url: /.*
      script: _go_app
  4. Assicurati di avere preparato un progetto Google Cloud con un'app App Engine e di aver inizializzato e configurato il comando gcloud per il progetto.

  5. Utilizza il comando gcloud app deploy per eseguire il deployment dell'app in App Engine.

  6. Guarda l'app in azione usando il comando gcloud app browse.