@cryptotaxi247 / kubo / commits / f9f3c6a52

make offline commands respect timeout

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

Jeromy committed Jul 20, 2015 at 14:34 UTC f9f3c6a5277811ed9d0117535461156c54980419
6 files changed +41 -31
cmd/ipfs/main.go
+7
@@ -335,6 +335,13 @@ func callCommand(ctx context.Context, req cmds.Request, root *cmds.Command, cmd
335 } else {
336 log.Debug("Executing command locally")
337
338 + ctx, err := cmds.GetContext(ctx, req)
339 + if err != nil {
340 + return nil, err
341 + }
342 +
343 + req.Context().Context = ctx
344 +
345 // Okay!!!!! NOW we can call the command.
346 res = root.Call(req)
347
commands/http/handler.go
+1 -21
@@ -7,10 +7,8 @@ import (
7 "net/http"
8 "strconv"
9 "strings"
10 - "time"
10
11 "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"
12
13 cmds "github.com/ipfs/go-ipfs/commands"
14 u "github.com/ipfs/go-ipfs/util"
@@ -108,31 +106,13 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
106 return
107 }
108
111 - tout, found, err := req.Option("timeout").String()
109 + ctx, err := cmds.GetContext(node.Context(), req)
110 if err != nil {
111 err = fmt.Errorf("error parsing timeout option: %s", err)
112 http.Error(w, err.Error(), http.StatusInternalServerError)
113 return
114 }
115
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 -
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 -
116 //ps: take note of the name clash - commands.Context != context.Context
117 cmdctx := i.ctx
118 cmdctx.Context = ctx
commands/request.go
+23
@@ -7,6 +7,7 @@ import (
7 "os"
8 "reflect"
9 "strconv"
10 + "time"
11
12 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
13 "github.com/ipfs/go-ipfs/commands/files"
@@ -297,3 +298,25 @@ func NewRequest(path []string, opts OptMap, args []string, file files.File, cmd
298
299 return req, nil
300 }
301 +
302 +func GetContext(base context.Context, req Request) (context.Context, error) {
303 + tout, found, err := req.Option("timeout").String()
304 + if err != nil {
305 + return nil, fmt.Errorf("error parsing timeout option: %s", err)
306 + }
307 +
308 + var ctx context.Context
309 + if found {
310 + duration, err := time.ParseDuration(tout)
311 + if err != nil {
312 + return nil, fmt.Errorf("error parsing timeout option: %s", err)
313 + }
314 +
315 + tctx, _ := context.WithTimeout(base, duration)
316 + ctx = tctx
317 + } else {
318 + cctx, _ := context.WithCancel(base)
319 + ctx = cctx
320 + }
321 + return ctx, nil
322 +}
core/commands/pin.go
+7 -2
@@ -60,7 +60,12 @@ on disk.
60 recursive = false
61 }
62
63 - added, err := corerepo.Pin(n, req.Arguments(), recursive)
63 + go func() {
64 + <-req.Context().Context.Done()
65 + log.Error("CONTEXT IS OVER!")
66 + }()
67 +
68 + added, err := corerepo.Pin(n, req.Context().Context, req.Arguments(), recursive)
69 if err != nil {
70 res.SetError(err, cmds.ErrNormal)
71 return
@@ -125,7 +130,7 @@ collected if needed.
130 recursive = false // default
131 }
132
128 - removed, err := corerepo.Unpin(n, req.Arguments(), recursive)
133 + removed, err := corerepo.Unpin(n, req.Context().Context, req.Arguments(), recursive)
134 if err != nil {
135 res.SetError(err, cmds.ErrNormal)
136 return
core/corerepo/pinning.go
+2 -7
@@ -25,10 +25,7 @@ import (
25 path "github.com/ipfs/go-ipfs/path"
26 )
27
28 -func Pin(n *core.IpfsNode, paths []string, recursive bool) ([]key.Key, error) {
29 - // TODO(cryptix): do we want a ctx as first param for (Un)Pin() as well, just like core.Resolve?
30 - ctx := n.Context()
31 -
28 +func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]key.Key, error) {
29 dagnodes := make([]*merkledag.Node, 0)
30 for _, fpath := range paths {
31 dagnode, err := core.Resolve(ctx, n, path.Path(fpath))
@@ -62,9 +59,7 @@ func Pin(n *core.IpfsNode, paths []string, recursive bool) ([]key.Key, error) {
59 return out, nil
60 }
61
65 -func Unpin(n *core.IpfsNode, paths []string, recursive bool) ([]key.Key, error) {
66 - // TODO(cryptix): do we want a ctx as first param for (Un)Pin() as well, just like core.Resolve?
67 - ctx := n.Context()
62 +func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]key.Key, error) {
63
64 dagnodes := make([]*merkledag.Node, 0)
65 for _, fpath := range paths {
test/sharness/t0081-repo-pinning.sh
+1 -1
@@ -242,7 +242,7 @@ test_expect_success "some are no longer there" '
242
243 test_expect_success "recursive pin fails without objects" '
244 ipfs pin rm "$HASH_DIR1" &&
245 - test_must_fail ipfs pin add -r "$HASH_DIR1" 2>err_expected8 &&
245 + test_must_fail ipfs pin add -r "$HASH_DIR1" --timeout=500ms 2>err_expected8 &&
246 grep "context deadline exceeded" err_expected8
247 '
248