Add timeout subcommand to scan/search commands.

Use per-query timeout for those commands, if it was given.
This commit is contained in:
Alex Roitman 2019-04-24 12:02:39 -07:00
parent 0aecef6a5c
commit e514a0287f
5 changed files with 34 additions and 1 deletions

View File

@ -13,6 +13,11 @@ func New(deadline time.Time) *Deadline {
return &Deadline{unixNano: deadline.UnixNano()} return &Deadline{unixNano: deadline.UnixNano()}
} }
// Update the deadline from a given time object
func (deadline *Deadline) Update(newDeadline time.Time) {
deadline.unixNano = newDeadline.UnixNano()
}
// Check the deadline and panic when reached // Check the deadline and panic when reached
//go:noinline //go:noinline
func (deadline *Deadline) Check() { func (deadline *Deadline) Check() {

View File

@ -55,6 +55,9 @@ func (c *Server) cmdScan(msg *Message) (res resp.Value, err error) {
wr.WriteString(`{"ok":true`) wr.WriteString(`{"ok":true`)
} }
sw.writeHead() sw.writeHead()
if s.timeout != 0 {
msg.Deadline.Update(start.Add(s.timeout))
}
if sw.col != nil { if sw.col != nil {
if sw.output == outputCount && len(sw.wheres) == 0 && if sw.output == outputCount && len(sw.wheres) == 0 &&
len(sw.whereins) == 0 && sw.globEverything == true { len(sw.whereins) == 0 && sw.globEverything == true {

View File

@ -370,6 +370,9 @@ func (server *Server) cmdNearby(msg *Message) (res resp.Value, err error) {
wr.WriteString(`{"ok":true`) wr.WriteString(`{"ok":true`)
} }
sw.writeHead() sw.writeHead()
if s.timeout != 0 {
msg.Deadline.Update(start.Add(s.timeout))
}
if sw.col != nil { if sw.col != nil {
iter := func(id string, o geojson.Object, fields []float64, dist float64) bool { iter := func(id string, o geojson.Object, fields []float64, dist float64) bool {
meters := 0.0 meters := 0.0
@ -480,6 +483,9 @@ func (server *Server) cmdWithinOrIntersects(cmd string, msg *Message) (res resp.
wr.WriteString(`{"ok":true`) wr.WriteString(`{"ok":true`)
} }
sw.writeHead() sw.writeHead()
if s.timeout != 0 {
msg.Deadline.Update(start.Add(s.timeout))
}
if sw.col != nil { if sw.col != nil {
if cmd == "within" { if cmd == "within" {
sw.col.Within(s.obj, s.sparse, sw, msg.Deadline, func( sw.col.Within(s.obj, s.sparse, sw, msg.Deadline, func(
@ -570,6 +576,9 @@ func (server *Server) cmdSearch(msg *Message) (res resp.Value, err error) {
wr.WriteString(`{"ok":true`) wr.WriteString(`{"ok":true`)
} }
sw.writeHead() sw.writeHead()
if s.timeout != 0 {
msg.Deadline.Update(start.Add(s.timeout))
}
if sw.col != nil { if sw.col != nil {
if sw.output == outputCount && len(sw.wheres) == 0 && sw.globEverything == true { if sw.output == outputCount && len(sw.wheres) == 0 && sw.globEverything == true {
count := sw.col.Count() - int(s.cursor) count := sw.col.Count() - int(s.cursor)

View File

@ -1024,7 +1024,7 @@ func (server *Server) handleInputCommand(client *Client, msg *Message) error {
// No locking for pubsub // No locking for pubsub
} }
res, d, err := func() (res resp.Value, d commandDetails, err error) { res, d, err := func() (res resp.Value, d commandDetails, err error) {
if client.timeout != 0 && !write { if !write {
msg.Deadline = deadline.New(start.Add(client.timeout)) msg.Deadline = deadline.New(start.Add(client.timeout))
defer func() { defer func() {
if msg.Deadline.Hit() { if msg.Deadline.Hit() {

View File

@ -6,6 +6,7 @@ import (
"math" "math"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/yuin/gopher-lua" "github.com/yuin/gopher-lua"
) )
@ -247,6 +248,7 @@ type searchScanBaseTokens struct {
sparse uint8 sparse uint8
desc bool desc bool
clip bool clip bool
timeout time.Duration
} }
func (c *Server) parseSearchScanBaseTokens( func (c *Server) parseSearchScanBaseTokens(
@ -579,6 +581,20 @@ func (c *Server) parseSearchScanBaseTokens(
} }
t.clip = true t.clip = true
continue continue
case "timeout":
vs = nvs
var valStr string
if vs, valStr, ok = tokenval(vs); !ok || valStr == "" {
err = errInvalidNumberOfArguments
return
}
timeout, _err := strconv.ParseFloat(valStr, 64)
if _err != nil || timeout < 0 {
err = errInvalidArgument(valStr)
return
}
t.timeout = time.Duration(timeout * float64(time.Second))
continue
} }
} }
break break