@cryptotaxi247 / kubo / commits / 608300798

add a global timeout flag for to be setting timeouts

License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>

Jeromy committed Jul 20, 2015 at 12:34 UTC 608300798745edbfb76d8572b37f2efa82e76d55
4 files changed +38 -19
commands/http/handler.go
+28 -11
@@ -7,6 +7,7 @@ import (
7 "net/http"
8 "strconv"
9 "strings"
10 + "time"
11
12 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/rs/cors"
13 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
@@ -106,20 +107,36 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
107 http.Error(w, err.Error(), http.StatusInternalServerError)
108 return
109 }
109 - ctx, cancel := context.WithCancel(node.Context())
110 - defer cancel()
111 - /*
112 - TODO(cryptix): the next line looks very fishy to me..
113 - It looks like the the context for the command request beeing prepared here is shared across all incoming requests..
110
115 - I assume it really isn't because ServeHTTP() doesn't take a pointer receiver, but it's really subtule..
111 + tout, found, err := req.Option("timeout").String()
112 + if err != nil {
113 + err = fmt.Errorf("error parsing timeout option: %s", err)
114 + http.Error(w, err.Error(), http.StatusInternalServerError)
115 + return
116 + }
117 +
118 + var ctx context.Context
119 + if found {
120 + duration, err := time.ParseDuration(tout)
121 + if err != nil {
122 + err = fmt.Errorf("error parsing timeout option: %s", err)
123 + http.Error(w, err.Error(), http.StatusInternalServerError)
124 + return
125 + }
126
117 - Shouldn't the context be just put on the command request?
127 + tctx, cancel := context.WithTimeout(node.Context(), duration)
128 + defer cancel()
129 + ctx = tctx
130 + } else {
131 + cctx, cancel := context.WithCancel(node.Context())
132 + defer cancel()
133 + ctx = cctx
134 + }
135
119 - ps: take note of the name clash - commands.Context != context.Context
120 - */
121 - i.ctx.Context = ctx
122 - req.SetContext(i.ctx)
136 + //ps: take note of the name clash - commands.Context != context.Context
137 + cmdctx := i.ctx
138 + cmdctx.Context = ctx
139 + req.SetContext(cmdctx)
140
141 // call the command
142 res := i.root.Call(req)
commands/option.go
+8 -5
@@ -154,22 +154,25 @@ func (ov OptionValue) String() (value string, found bool, err error) {
154
155 // Flag names
156 const (
157 - EncShort = "enc"
158 - EncLong = "encoding"
159 - RecShort = "r"
160 - RecLong = "recursive"
161 - ChanOpt = "stream-channels"
157 + EncShort = "enc"
158 + EncLong = "encoding"
159 + RecShort = "r"
160 + RecLong = "recursive"
161 + ChanOpt = "stream-channels"
162 + TimeoutOpt = "timeout"
163 )
164
165 // options that are used by this package
166 var OptionEncodingType = StringOption(EncShort, EncLong, "The encoding type the output should be encoded with (json, xml, or text)")
167 var OptionRecursivePath = BoolOption(RecShort, RecLong, "Add directory paths recursively")
168 var OptionStreamChannels = BoolOption(ChanOpt, "Stream channel output")
169 +var OptionTimeout = StringOption(TimeoutOpt, "set a global timeout on the command")
170
171 // global options, added to every command
172 var globalOptions = []Option{
173 OptionEncodingType,
174 OptionStreamChannels,
175 + OptionTimeout,
176 }
177
178 // the above array of Options, wrapped in a Command
core/commands/block.go
+1 -2
@@ -9,7 +9,6 @@ import (
9 "strings"
10
11 mh "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
12 - "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
12 "github.com/ipfs/go-ipfs/blocks"
13 key "github.com/ipfs/go-ipfs/blocks/key"
14 cmds "github.com/ipfs/go-ipfs/commands"
@@ -178,7 +177,7 @@ func getBlockForKey(req cmds.Request, skey string) (*blocks.Block, error) {
177 }
178
179 k := key.Key(h)
181 - b, err := n.Blocks.GetBlock(context.TODO(), k)
180 + b, err := n.Blocks.GetBlock(req.Context().Context, k)
181 if err != nil {
182 return nil, err
183 }
core/commands/ls.go
+1 -1
@@ -81,7 +81,7 @@ it contains, with the following format:
81 Links: make([]LsLink, len(dagnode.Links)),
82 }
83 for j, link := range dagnode.Links {
84 - ctx, cancel := context.WithTimeout(context.TODO(), time.Minute)
84 + ctx, cancel := context.WithTimeout(req.Context().Context, time.Minute)
85 defer cancel()
86 link.Node, err = link.GetNode(ctx, node.DAG)
87 if err != nil {