Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: common/gcloud/gs/gs.go

Issue 1844253002: Fix GS client breakage, remove offset hacks. (Closed) Base URL: https://github.com/luci/luci-go@subscriber-update
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | common/gcloud/gs/opts.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package gs 5 package gs
6 6
7 import ( 7 import (
8 "io" 8 "io"
9 "net/http" 9 "net/http"
10 "time" 10 "time"
(...skipping 26 matching lines...) Expand all
37 37
38 // NewReader instantiates a new Reader instance for the named bucket/pat h. 38 // NewReader instantiates a new Reader instance for the named bucket/pat h.
39 NewReader(bucket, relpath string, o Options) (io.ReadCloser, error) 39 NewReader(bucket, relpath string, o Options) (io.ReadCloser, error)
40 // NewWriter instantiates a new Writer instance for the named bucket/pat h. 40 // NewWriter instantiates a new Writer instance for the named bucket/pat h.
41 NewWriter(bucket, relpath string) (Writer, error) 41 NewWriter(bucket, relpath string) (Writer, error)
42 // Delete deletes the named Google Storage object. If the object doesn't 42 // Delete deletes the named Google Storage object. If the object doesn't
43 // exist, a nil error will be returned. 43 // exist, a nil error will be returned.
44 Delete(bucket, relpath string) error 44 Delete(bucket, relpath string) error
45 } 45 }
46 46
47 // Options are the set of extra options to apply to the Google Storage request.
48 type Options struct {
49 // From is the range request starting index. If >0, the beginning of the
50 // range request will be set.
51 From int64
52 // To is the range request ending index. If >0, the end of the
53 // range request will be set.
54 //
55 // If no From index is set, this will result in a request indexed from t he end
56 // of the object.
57 To int64
58 }
59
47 // prodGSObject is an implementation of Client interface using the production 60 // prodGSObject is an implementation of Client interface using the production
48 // Google Storage client. 61 // Google Storage client.
49 type prodClient struct { 62 type prodClient struct {
50 context.Context 63 context.Context
51 64
52 » // rt is the http.RoundTripper to use for communication. 65 » // rt is the RoundTripper to use, or nil for the cloud service default.
53 rt http.RoundTripper 66 rt http.RoundTripper
54 // baseClient is a basic Google Storage client instance. It is used for 67 // baseClient is a basic Google Storage client instance. It is used for
55 // operations that don't need custom header injections. 68 // operations that don't need custom header injections.
56 baseClient *gs.Client 69 baseClient *gs.Client
57 } 70 }
58 71
59 // NewProdClient creates a new Client instance that uses production Cloud 72 // NewProdClient creates a new Client instance that uses production Cloud
60 // Storage. 73 // Storage.
61 // 74 //
62 // The supplied RoundTripper will be used to make connections. If nil, 75 // The supplied RoundTripper will be used to make connections. If nil, the
63 // the default http.Client RoundTripper will be used. 76 // default HTTP client will be used.
64 func NewProdClient(ctx context.Context, rt http.RoundTripper) (Client, error) { 77 func NewProdClient(ctx context.Context, rt http.RoundTripper) (Client, error) {
65 c := prodClient{ 78 c := prodClient{
66 Context: ctx, 79 Context: ctx,
67 rt: rt, 80 rt: rt,
68 } 81 }
69 var err error 82 var err error
70 » c.baseClient, err = c.newClient(nil) 83 » c.baseClient, err = c.newClient()
71 if err != nil { 84 if err != nil {
72 return nil, err 85 return nil, err
73 } 86 }
74 return &c, nil 87 return &c, nil
75 } 88 }
76 89
77 func (c *prodClient) Close() error { 90 func (c *prodClient) Close() error {
78 return c.baseClient.Close() 91 return c.baseClient.Close()
79 } 92 }
80 93
81 func (c *prodClient) NewWriter(bucket, relpath string) (Writer, error) { 94 func (c *prodClient) NewWriter(bucket, relpath string) (Writer, error) {
82 return &prodWriter{ 95 return &prodWriter{
83 Context: c, 96 Context: c,
84 client: c, 97 client: c,
85 bucket: bucket, 98 bucket: bucket,
86 relpath: relpath, 99 relpath: relpath,
87 }, nil 100 }, nil
88 } 101 }
89 102
90 func (c *prodClient) NewReader(bucket, relpath string, o Options) (io.ReadCloser , error) { 103 func (c *prodClient) NewReader(bucket, relpath string, o Options) (io.ReadCloser , error) {
91 » client, err := c.newClient(&o) 104 » if o.From < 0 {
92 » if err != nil { 105 » » o.From = 0
93 » » return nil, err
94 } 106 }
95 » return client.Bucket(bucket).Object(relpath).NewReader(c) 107 » if o.To <= 0 {
108 » » o.To = -1
109 » }
110 » return c.baseClient.Bucket(bucket).Object(relpath).NewRangeReader(c, o.F rom, o.To)
96 } 111 }
97 112
98 func (c *prodClient) Delete(bucket, relpath string) error { 113 func (c *prodClient) Delete(bucket, relpath string) error {
99 obj := c.baseClient.Bucket(bucket).Object(relpath) 114 obj := c.baseClient.Bucket(bucket).Object(relpath)
100 return retry.Retry(c, retry.TransientOnly(retry.Default), func() error { 115 return retry.Retry(c, retry.TransientOnly(retry.Default), func() error {
101 if err := obj.Delete(c); err != nil { 116 if err := obj.Delete(c); err != nil {
102 // The storage library doesn't return gs.ErrObjectNotExi st when Delete 117 // The storage library doesn't return gs.ErrObjectNotExi st when Delete
103 // returns a 404. Catch that explicitly. 118 // returns a 404. Catch that explicitly.
104 if t, ok := err.(*googleapi.Error); ok { 119 if t, ok := err.(*googleapi.Error); ok {
105 switch t.Code { 120 switch t.Code {
(...skipping 10 matching lines...) Expand all
116 }, func(err error, d time.Duration) { 131 }, func(err error, d time.Duration) {
117 log.Fields{ 132 log.Fields{
118 log.ErrorKey: err, 133 log.ErrorKey: err,
119 "delay": d, 134 "delay": d,
120 "bucket": bucket, 135 "bucket": bucket,
121 "path": relpath, 136 "path": relpath,
122 }.Warningf(c, "Transient error deleting GS file. Retrying...") 137 }.Warningf(c, "Transient error deleting GS file. Retrying...")
123 }) 138 })
124 } 139 }
125 140
126 func (c *prodClient) newClient(o *Options) (*gs.Client, error) { 141 func (c *prodClient) newClient() (*gs.Client, error) {
127 » rt := c.rt 142 » var optsArray [1]cloud.ClientOption
128 » if rt == nil { 143 » opts := optsArray[:0]
129 » » rt = http.DefaultTransport 144 » if c.rt != nil {
145 » » opts = append(opts, cloud.WithBaseHTTP(&http.Client{
146 » » » Transport: c.rt,
147 » » }))
130 } 148 }
131 149 » return gs.NewClient(c, opts...)
132 » // This is a hack. Unfortunately, it is necessary since the Cloud Storag e API
133 » // doesn't support setting range request headers. This installation enab les
134 » // us to request ranges from Cloud Storage objects, which is super usefu l for
135 » // range requests since we have an index.
136 » //
137 » // The Client construction logic is taken from here:
138 » // https://godoc.org/google.golang.org/cloud/internal/transport#NewHTTPC lient
139 » //
140 » // We have to replicate the token source confguration b/c our only entry point
141 » // into header editing is the "cloud.WithClient", which preempts all of the
142 » // token source generation logic.
143 » if o != nil {
144 » » rt = &gsRoundTripper{
145 » » » RoundTripper: rt,
146 » » » Options: o,
147 » » }
148 » }
149 » client := http.Client{
150 » » Transport: rt,
151 » }
152
153 » gsc, err := gs.NewClient(c, cloud.WithBaseHTTP(&client))
154 » if err != nil {
155 » » return nil, err
156 » }
157
158 » return gsc, nil
159 } 150 }
OLDNEW
« no previous file with comments | « no previous file | common/gcloud/gs/opts.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698