@@ -22,20 +22,23 @@ import (
22
22
"context"
23
23
"errors"
24
24
"fmt"
25
+ "io"
25
26
"strings"
26
27
"time"
27
28
28
29
"github.com/RichardKnop/machinery/v1"
29
- "github.com/go-http-utils/headers"
30
30
"github.com/go-playground/validator/v10"
31
+ "google.golang.org/grpc/codes"
32
+ "google.golang.org/grpc/status"
31
33
32
34
cdnsystemv1 "d7y.io/api/v2/pkg/apis/cdnsystem/v1"
33
35
commonv1 "d7y.io/api/v2/pkg/apis/common/v1"
36
+ commonv2 "d7y.io/api/v2/pkg/apis/common/v2"
37
+ dfdaemonv2 "d7y.io/api/v2/pkg/apis/dfdaemon/v2"
34
38
35
39
logger "d7y.io/dragonfly/v2/internal/dflog"
36
40
internaljob "d7y.io/dragonfly/v2/internal/job"
37
41
"d7y.io/dragonfly/v2/pkg/idgen"
38
- "d7y.io/dragonfly/v2/pkg/net/http"
39
42
"d7y.io/dragonfly/v2/scheduler/config"
40
43
"d7y.io/dragonfly/v2/scheduler/resource"
41
44
)
@@ -148,8 +151,9 @@ func (j *job) Serve() {
148
151
}()
149
152
}
150
153
151
- // preheat is a job to preheat.
152
- func (j * job ) preheat (ctx context.Context , req string ) error {
154
+ // preheat is a job to preheat, it is not supported to preheat
155
+ // with range requests.
156
+ func (j * job ) preheat (ctx context.Context , data string ) error {
153
157
ctx , cancel := context .WithTimeout (ctx , preheatTimeout )
154
158
defer cancel ()
155
159
@@ -163,63 +167,120 @@ func (j *job) preheat(ctx context.Context, req string) error {
163
167
return fmt .Errorf ("cluster %d scheduler %s has no available seed peer" , j .config .Manager .SchedulerClusterID , j .config .Server .AdvertiseIP )
164
168
}
165
169
166
- preheat := & internaljob.PreheatRequest {}
167
- if err := internaljob .UnmarshalRequest (req , preheat ); err != nil {
168
- logger .Errorf ("unmarshal request err: %s, request body: %s" , err .Error (), req )
170
+ req := & internaljob.PreheatRequest {}
171
+ if err := internaljob .UnmarshalRequest (data , req ); err != nil {
172
+ logger .Errorf ("unmarshal request err: %s, request body: %s" , err .Error (), data )
169
173
return err
170
174
}
171
175
172
- if err := validator .New ().Struct (preheat ); err != nil {
173
- logger .Errorf ("preheat %s validate failed: %s" , preheat .URL , err .Error ())
176
+ if err := validator .New ().Struct (req ); err != nil {
177
+ logger .Errorf ("preheat %s validate failed: %s" , req .URL , err .Error ())
174
178
return err
175
179
}
176
180
177
- urlMeta := & commonv1.UrlMeta {
178
- Digest : preheat .Digest ,
179
- Tag : preheat .Tag ,
180
- Filter : preheat .FilteredQueryParams ,
181
- Header : preheat .Headers ,
182
- Application : preheat .Application ,
183
- Priority : commonv1 .Priority (preheat .Priority ),
184
- }
185
- if preheat .Headers != nil {
186
- if r , ok := preheat .Headers [headers .Range ]; ok {
187
- // Range in dragonfly is without "bytes=".
188
- urlMeta .Range = strings .TrimPrefix (r , http .RangePrefix )
181
+ // Preheat by v2 grpc protocol. If seed peer does not support
182
+ // v2 protocol, preheat by v1 grpc protocol.
183
+ if err := j .preheatV2 (ctx , req ); err != nil {
184
+ logger .Errorf ("preheat %s failed: %s" , req .URL , err .Error ())
185
+
186
+ if st , ok := status .FromError (err ); ok {
187
+ if st .Code () == codes .Unimplemented {
188
+ if err := j .preheatV1 (ctx , req ); err != nil {
189
+ return err
190
+ }
191
+
192
+ return nil
193
+ }
189
194
}
195
+
196
+ return err
197
+ }
198
+
199
+ return nil
200
+ }
201
+
202
+ // preheatV1 preheats job by v1 grpc protocol.
203
+ func (j * job ) preheatV1 (ctx context.Context , req * internaljob.PreheatRequest ) error {
204
+ urlMeta := & commonv1.UrlMeta {
205
+ Digest : req .Digest ,
206
+ Tag : req .Tag ,
207
+ Filter : req .FilteredQueryParams ,
208
+ Header : req .Headers ,
209
+ Application : req .Application ,
210
+ Priority : commonv1 .Priority (req .Priority ),
190
211
}
191
212
192
213
// Trigger seed peer download seeds.
193
- taskID := idgen .TaskIDV1 (preheat .URL , urlMeta )
194
- log := logger .WithTask (taskID , preheat .URL )
195
- log .Infof ("preheat %s tag: %s, range: %s, filtered query params: %s, digest: %s" ,
196
- preheat .URL , urlMeta .Tag , urlMeta .Range , urlMeta .Filter , urlMeta .Digest )
197
- log .Debugf ("preheat %s headers: %#v" , preheat .URL , urlMeta .Header )
214
+ taskID := idgen .TaskIDV1 (req .URL , urlMeta )
215
+ log := logger .WithTask (taskID , req .URL )
216
+ log .Infof ("preheat(v1) %s tag: %s, filtered query params: %s, digest: %s, headers: %#v" ,
217
+ req .URL , urlMeta .Tag , urlMeta .Filter , urlMeta .Digest , urlMeta .Header )
198
218
199
219
stream , err := j .resource .SeedPeer ().Client ().ObtainSeeds (ctx , & cdnsystemv1.SeedRequest {
200
220
TaskId : taskID ,
201
- Url : preheat .URL ,
221
+ Url : req .URL ,
202
222
UrlMeta : urlMeta ,
203
223
})
204
224
if err != nil {
205
- log .Errorf ("preheat %s failed: %s" , preheat .URL , err .Error ())
225
+ log .Errorf ("preheat(v1) %s failed: %s" , req .URL , err .Error ())
206
226
return err
207
227
}
208
228
209
229
for {
210
230
piece , err := stream .Recv ()
211
231
if err != nil {
212
- log .Errorf ("preheat %s recive piece failed: %s" , preheat .URL , err .Error ())
232
+ log .Errorf ("preheat(v1) %s recive piece failed: %s" , req .URL , err .Error ())
213
233
return err
214
234
}
215
235
216
236
if piece .Done == true {
217
- log .Infof ("preheat %s succeeded" , preheat .URL )
237
+ log .Infof ("preheat(v1) %s succeeded" , req .URL )
218
238
return nil
219
239
}
220
240
}
221
241
}
222
242
243
+ // preheatV2 preheats job by v2 grpc protocol.
244
+ func (j * job ) preheatV2 (ctx context.Context , req * internaljob.PreheatRequest ) error {
245
+ filteredQueryParams := strings .Split (req .FilteredQueryParams , idgen .FilteredQueryParamsSeparator )
246
+ taskID := idgen .TaskIDV2 (req .URL , req .Digest , req .Tag , req .Application , int32 (req .PieceLength ), filteredQueryParams )
247
+
248
+ log := logger .WithTask (taskID , req .URL )
249
+ log .Infof ("preheat(v2) %s tag: %s, filtered query params: %s, digest: %s, headers: %#v" ,
250
+ req .URL , req .Tag , req .FilteredQueryParams , req .Digest , req .Headers )
251
+
252
+ stream , err := j .resource .SeedPeer ().Client ().DownloadTask (ctx , taskID , & dfdaemonv2.DownloadTaskRequest {
253
+ Download : & commonv2.Download {
254
+ Url : req .URL ,
255
+ Digest : & req .Digest ,
256
+ Type : commonv2 .TaskType_DFDAEMON ,
257
+ Tag : & req .Tag ,
258
+ Application : & req .Application ,
259
+ Priority : commonv2 .Priority (req .Priority ),
260
+ FilteredQueryParams : filteredQueryParams ,
261
+ RequestHeader : req .Headers ,
262
+ PieceLength : uint32 (req .PieceLength ),
263
+ }})
264
+ if err != nil {
265
+ logger .Errorf ("preheat(v2) %s failed: %s" , req .URL , err .Error ())
266
+ return err
267
+ }
268
+
269
+ // Wait for the download task to complete.
270
+ for {
271
+ _ , err := stream .Recv ()
272
+ if err != nil {
273
+ if err == io .EOF {
274
+ log .Infof ("preheat(v2) %s succeeded" , req .URL )
275
+ return nil
276
+ }
277
+
278
+ log .Errorf ("preheat(v2) %s recive piece failed: %s" , req .URL , err .Error ())
279
+ return err
280
+ }
281
+ }
282
+ }
283
+
223
284
// syncPeers is a job to sync peers.
224
285
func (j * job ) syncPeers () (string , error ) {
225
286
var hosts []* resource.Host
0 commit comments