func walkOnce( dst farm.Selecter, wait waiter, src <-chan []string, maxSize int, instr instrumentation.WalkInstrumentation, ) { for batch := range src { log.Printf("walk: received batch of %d, requesting tokens", len(batch)) wait.Wait(int64(len(batch))) log.Printf("walk: received tokens, performing Select") dst.Select(batch, 0, maxSize) instr.WalkKeys(len(batch)) log.Printf("walk: performed Select, waiting for next batch") } }
func handleSelect(selecter farm.Selecter) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { began := time.Now() if err := r.ParseForm(); err != nil { respondError(w, r.Method, r.URL.String(), http.StatusInternalServerError, err) return } offset := parseInt(r.Form, "offset", 0) limit := parseInt(r.Form, "limit", 10) coalesce := parseBool(r.Form, "coalesce", false) var keys [][]byte defer r.Body.Close() if err := json.NewDecoder(r.Body).Decode(&keys); err != nil { respondError(w, r.Method, r.URL.String(), http.StatusBadRequest, err) return } keyStrings := make([]string, len(keys)) for i := range keys { keyStrings[i] = string(keys[i]) } var records interface{} if coalesce { // We need to Select from 0 to offset+limit, flatten the map to a // single ordered slice, and then cut off the last limit elements. m, err := selecter.Select(keyStrings, 0, offset+limit) if err != nil { respondError(w, r.Method, r.URL.String(), http.StatusInternalServerError, err) return } records = flatten(m, offset, limit) } else { // We can directly Select using the given offset and limit. m, err := selecter.Select(keyStrings, offset, limit) if err != nil { respondError(w, r.Method, r.URL.String(), http.StatusInternalServerError, err) return } records = m } respondSelected(w, keys, offset, limit, records, time.Since(began)) } }