Skip to content

Commit 0043b2a

Browse files
zhaoxianhuagithubgxll
authored andcommitted
[fix][dingospeed] Fix single file online and offline download
1 parent d385f6d commit 0043b2a

12 files changed

Lines changed: 117 additions & 56 deletions

File tree

config/config.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ server:
77
metrics: true
88
online: true #true表示本地找不到,去hfNetLoc地址查找并下载模型数据,false表示本地如果没有,直接返回没有
99
repos: ./repos
10-
hfNetLoc: huggingface.co # huggingface.co
10+
hfNetLoc: hf-mirror.com # huggingface.co
1111
bpHfNetLoc: hf-mirror.com #hf-mirror.com
1212
hfScheme: https
1313
ssl:
@@ -16,7 +16,7 @@ server:
1616
caFile: ./config/ssl/ca.crt
1717

1818
scheduler:
19-
mode: cluster #运行的两种模式:standalone&cluster,default:standalone
19+
mode: standalone #运行的两种模式:standalone&cluster,default:standalone
2020
addr: 10.230.203.240:19091 # 调度器地址 10.230.204.102:19091
2121
strategy: #在cluster模型下,文件调度策略
2222
minimumFileSize: 0 # 文件参与调度最小值,单位字节
@@ -26,7 +26,8 @@ scheduler:
2626
host: 10.230.203.240
2727
port: 8090
2828
heartbeatPeriod: 5 # 心跳周期,单位秒
29-
publicDomain: http://hfmirror.mas.zetyun.cn:8082
29+
publicDomain: http://hfmirror.mas.zetyun.cn:8082 #用于在Alayanew上文件下载的链接地址,通常为离线的域名,即8082。
30+
linkDomain: http://hfmirror.mas.zetyun.cn:8082 #用于的huggingface_hub调用/tree/main接口时替换的link地址,需和用户配置hf-endpoint域名保持一致。
3031

3132
download:
3233
blockSize: 8388608 #默认文件块大小为8MB(8388608),单位字节,1048576(1MB)

internal/dao/downloader_dao.go

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ package dao
1717
import (
1818
"context"
1919
"fmt"
20+
"net/http"
2021
"sync"
2122
"time"
2223

2324
"dingospeed/internal/downloader"
2425
"dingospeed/pkg/common"
2526
"dingospeed/pkg/config"
2627
"dingospeed/pkg/consts"
28+
myerr "dingospeed/pkg/error"
2729
"dingospeed/pkg/proto/manager"
2830
"dingospeed/pkg/util"
2931

@@ -41,22 +43,28 @@ func NewDownloaderDao(schedulerDao *SchedulerDao) *DownloaderDao {
4143
}
4244

4345
// 整个文件
44-
func (d *DownloaderDao) FileDownload(startPos, endPos int64, isInnerRequest bool, taskParam *downloader.TaskParam) {
46+
func (d *DownloaderDao) FileDownload(chanErr chan error, startPos, endPos int64, isInnerRequest bool, taskParam *downloader.TaskParam) {
4547
var (
4648
wg sync.WaitGroup
4749
)
50+
defer close(chanErr)
4851
defer close(taskParam.ResponseChan)
4952
dingCacheManager := downloader.GetInstance()
5053
dingFile, err := dingCacheManager.GetDingFile(taskParam.BlobsFile, taskParam.FileSize)
5154
if err != nil {
5255
zap.S().Errorf("GetDingFile err.%v", err)
56+
chanErr <- myerr.NewAppendCode(http.StatusInternalServerError, "Get DingFile err")
5357
return
5458
}
5559
defer func() {
5660
dingCacheManager.ReleasedDingFile(taskParam.BlobsFile)
5761
}()
5862
taskParam.DingFile = dingFile
59-
tasks := d.constructTask(startPos, endPos, isInnerRequest, taskParam)
63+
tasks, err := d.constructTask(startPos, endPos, isInnerRequest, taskParam)
64+
if err != nil {
65+
chanErr <- err
66+
return
67+
}
6068
wg.Add(1)
6169
go func() {
6270
defer func() {
@@ -85,21 +93,24 @@ func (d *DownloaderDao) FileDownload(startPos, endPos int64, isInnerRequest bool
8593
wg.Wait() // 等待协程池所有远程下载任务执行完毕
8694
}
8795

88-
func (d *DownloaderDao) constructTask(startPos, endPos int64, isInnerRequest bool, taskParam *downloader.TaskParam) []common.DownloadTask {
96+
func (d *DownloaderDao) constructTask(startPos, endPos int64, isInnerRequest bool, taskParam *downloader.TaskParam) ([]common.DownloadTask, error) {
8997
var (
90-
tasks []common.DownloadTask
91-
ctx = taskParam.Context
92-
existPosition bool
93-
curPos int64
98+
tasks []common.DownloadTask
99+
ctx = taskParam.Context
100+
fileComplete bool
101+
curPos int64
94102
)
95103
// 小于这个值的文件将不参与调度
96104
if taskParam.FileSize <= config.SysConfig.GetMinimumFileSize() {
97105
goto localTask
98106
}
99107
// 分析下载类型是否全部存在,若文件不完整,返回当前已缓存的最大偏移量
100-
existPosition, curPos = analysisFilePosition(taskParam.DingFile, startPos, endPos)
108+
fileComplete, curPos = analysisFilePosition(taskParam.DingFile, startPos, endPos)
109+
if !fileComplete && !config.SysConfig.Online() { // 文件不完整,且当前节点为离线
110+
return nil, myerr.NewAppendCode(http.StatusNotFound, "model file is not exist")
111+
}
101112
// isInnerRequest为true,即内部请求,是已经被调度过后,设置为内部域名的请求,这种请求将不会再次参与调度,直接做下载即可。
102-
if !isInnerRequest && config.SysConfig.IsCluster() && !existPosition {
113+
if !isInnerRequest && config.SysConfig.IsCluster() && !fileComplete {
103114
if response, err := d.getRequestDomainScheduler(taskParam.DataType, taskParam.OrgRepo, taskParam.FileName, taskParam.Etag, curPos, endPos, taskParam.FileSize); err != nil {
104115
zap.S().Errorf("getRequestDomainScheduler err.%v", err)
105116
goto localTask
@@ -125,7 +136,7 @@ func (d *DownloaderDao) constructTask(startPos, endPos int64, isInnerRequest boo
125136
afterTasks := getContiguousRanges(response.MaxOffset, endPos, taskParam)
126137
tasks = append(tasks, afterTasks...)
127138
}
128-
return tasks
139+
return tasks, nil
129140
} else {
130141
goto localTask
131142
}
@@ -137,7 +148,7 @@ func (d *DownloaderDao) constructTask(startPos, endPos int64, isInnerRequest boo
137148
localTask:
138149
taskParam.Domain = config.SysConfig.GetHFURLBase()
139150
tasks = getContiguousRanges(startPos, endPos, taskParam)
140-
return tasks
151+
return tasks, nil
141152
}
142153

143154
func (d *DownloaderDao) getRequestDomainScheduler(dataType, orgRepo, fileName, etag string, startPos, endPos, fileSize int64) (*manager.SchedulerFileResponse, error) {
@@ -197,7 +208,7 @@ func analysisFilePosition(dingFile *downloader.DingCache, startPos, endPos int64
197208
return true, startPos
198209
}
199210
if startPos < 0 || endPos <= startPos || endPos > dingFile.GetFileSize() {
200-
zap.S().Errorf("Invalid startPos/endPos: path=%s, startPos=%d, endPos=%d", dingFile.GetPath(), startPos, endPos)
211+
zap.S().Errorf("Invalid startPos/endPos: path=%s, startPos=%d, endPos=%d, filesize:%d", dingFile.GetPath(), startPos, endPos, dingFile.GetFileSize())
201212
return false, startPos
202213
}
203214
startBlock := startPos / dingFile.GetBlockSize()

internal/dao/file_dao.go

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func (f *FileDao) CheckCommitHf(repoType, orgRepo, commit, authorization string)
6666
return resp.StatusCode, myerr.New("request commit err")
6767
}
6868

69-
func (f *FileDao) GetFileCommitSha(repoType, orgRepo, commit, authorization string) (string, error) {
69+
func (f *FileDao) GetFileCommitSha(repoType, orgRepo, commit, authorization string, source string) (string, error) {
7070
metaShaKey := GetMetaShaRepoKey(orgRepo, commit, authorization)
7171
if v, ok := f.baseData.Cache.Get(metaShaKey); ok {
7272
return v.(string), nil
@@ -76,34 +76,41 @@ func (f *FileDao) GetFileCommitSha(repoType, orgRepo, commit, authorization stri
7676
err error
7777
)
7878
if config.SysConfig.Online() {
79-
code, sha, err := f.getCommitHfRemote(repoType, orgRepo, commit, authorization)
80-
if err != nil {
81-
return "", myerr.NewAppendCode(code, fmt.Sprintf("request fail.%v", err))
82-
}
83-
if code != http.StatusOK && code != http.StatusTemporaryRedirect {
84-
zap.S().Errorf("getFileCommitSha %s code:%d", orgRepo, code)
85-
if code == http.StatusNotFound {
86-
return "", myerr.NewAppendCode(code, "未找到该资源。")
87-
} else if code == http.StatusUnauthorized || code == http.StatusForbidden {
88-
return "", myerr.NewAppendCode(code, "没有该资源的访问权限,请联系管理员。")
89-
} else {
90-
return "", myerr.NewAppendCode(code, fmt.Sprintf("请求资源失败.(%d)", code))
91-
}
92-
} else {
93-
commitSha = sha
94-
}
95-
f.baseData.Cache.Set(metaShaKey, commitSha, config.SysConfig.GetDefaultExpiration())
96-
f.baseData.Cache.Set(GetMetaShaRepoKey(orgRepo, commitSha, authorization), commitSha, config.SysConfig.GetDefaultExpiration())
97-
return commitSha, nil
79+
goto remoteRequestMeta
9880
}
9981
commitSha, err = f.GetCommitHfOffline(repoType, orgRepo, commit)
10082
if err != nil {
101-
zap.S().Errorf("getFileCommitSha GetCommitHfOffline err.%v", err)
83+
if source == "file" {
84+
// 若只是发起文件下载(先在线后离线),将不会校验meta文件是否存在,没有就创建,主要是看文件本身是否存在。
85+
goto remoteRequestMeta
86+
}
87+
zap.S().Warnf("getFileCommitSha GetCommitHfOffline err.%v", err)
10288
return "", myerr.NewAppendCode(http.StatusNotFound, fmt.Sprintf("%s is not found", orgRepo))
10389
}
10490
f.baseData.Cache.Set(metaShaKey, commitSha, config.SysConfig.GetDefaultExpiration())
10591
f.baseData.Cache.Set(GetMetaShaRepoKey(orgRepo, commitSha, authorization), commitSha, config.SysConfig.GetDefaultExpiration())
10692
return commitSha, nil
93+
94+
remoteRequestMeta:
95+
code, sha, err := f.getCommitHfRemote(repoType, orgRepo, commit, authorization)
96+
if err != nil {
97+
return "", myerr.NewAppendCode(code, fmt.Sprintf("request fail.%v", err))
98+
}
99+
if code != http.StatusOK && code != http.StatusTemporaryRedirect {
100+
zap.S().Errorf("getFileCommitSha %s code:%d", orgRepo, code)
101+
if code == http.StatusNotFound {
102+
return "", myerr.NewAppendCode(code, "未找到该资源。")
103+
} else if code == http.StatusUnauthorized || code == http.StatusForbidden {
104+
return "", myerr.NewAppendCode(code, "没有该资源的访问权限,请联系管理员。")
105+
} else {
106+
return "", myerr.NewAppendCode(code, fmt.Sprintf("请求资源失败.(%d)", code))
107+
}
108+
} else {
109+
commitSha = sha
110+
}
111+
f.baseData.Cache.Set(metaShaKey, commitSha, config.SysConfig.GetDefaultExpiration())
112+
f.baseData.Cache.Set(GetMetaShaRepoKey(orgRepo, commitSha, authorization), commitSha, config.SysConfig.GetDefaultExpiration())
113+
return commitSha, nil
107114
}
108115

109116
// 若为离线或在线请求失败,将进行本地仓库查找。
@@ -176,7 +183,7 @@ func (f *FileDao) FileGetGenerator(c echo.Context, repoType, orgRepo, commit, fi
176183
pathInfo, err := f.GetPathsInfo(hfUri, repoType, orgRepo, commit, authorization, fileName)
177184
if err != nil {
178185
if e, ok := err.(myerr.Error); ok {
179-
zap.S().Errorf("GetPathsInfo code:%d, err:%v", e.StatusCode(), err)
186+
zap.S().Warnf("GetPathsInfo code:%d, err:%v", e.StatusCode(), err)
180187
return util.ErrorEntryUnknown(c, e.StatusCode(), e.Error())
181188
}
182189
zap.S().Errorf("GetPathsInfo err:%v", err)
@@ -448,8 +455,10 @@ func (f *FileDao) FileChunkGet(c echo.Context, taskParam *downloader.TaskParam,
448455
taskParam.Context = ctx
449456
taskParam.ResponseChan = responseChan
450457
taskParam.Cancel = cancel
451-
go f.downloaderDao.FileDownload(startPos, endPos, isInnerRequest, taskParam)
452-
if err := util.ResponseStream(c, fmt.Sprintf("%s/%s", taskParam.OrgRepo, taskParam.FileName), respHeaders, responseChan); err != nil {
458+
fileErrCh := make(chan error, 1)
459+
fileName := fmt.Sprintf("%s/%s", taskParam.OrgRepo, taskParam.FileName)
460+
go f.downloaderDao.FileDownload(fileErrCh, startPos, endPos, isInnerRequest, taskParam)
461+
if err := util.ResponseStream(ctx, c, fileName, respHeaders, responseChan, fileErrCh); err != nil {
453462
zap.S().Errorf("FileChunkGet stream err.%v", err)
454463
return util.ErrorProxyTimeout(c)
455464
}

internal/dao/meta_dao.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func (m *MetaDao) GetMetadata(repoType, orgRepo, revision, method, authorization
114114
lock := m.lockDao.getMetaDataReqLock(orgRepoKey)
115115
lock.Lock()
116116
defer lock.Unlock()
117-
commitSha, err := m.fileDao.GetFileCommitSha(repoType, orgRepo, revision, authorization)
117+
commitSha, err := m.fileDao.GetFileCommitSha(repoType, orgRepo, revision, authorization, "meta")
118118
if err != nil {
119119
return nil, err
120120
}

internal/downloader/bitset.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ type Bitset struct {
2727

2828
// NewBitset 创建一个新的 Bitset 对象
2929
func NewBitset(size uint64) *Bitset {
30+
if size < 0 {
31+
size = DEFAULT_BLOCK_MASK_MAX
32+
}
3033
return &Bitset{
3134
size: size,
3235
bits: make([]byte, (size+7)/8),

internal/downloader/file_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ func TestFileWrite2(t *testing.T) {
4747

4848
}
4949

50-
// func TestFileWrite3(t *testing.T) {
51-
// size := -18
52-
// s := make([]byte, (size+7)/8)
53-
// fmt.Println(len(s))
54-
// }
50+
func TestFileWrite3(t *testing.T) {
51+
size := -14
52+
s := make([]byte, (size+7)/8)
53+
fmt.Println(len(s))
54+
}

internal/handler/meta_handler.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package handler
1616

1717
import (
18+
"context"
1819
"net/http"
1920
"strings"
2021

@@ -68,7 +69,7 @@ func (handler *MetaHandler) GetMetadataHandler(c echo.Context) error {
6869
var bodyStreamChan = make(chan []byte, consts.RespChanSize)
6970
bodyStreamChan <- cacheContent.OriginContent
7071
close(bodyStreamChan)
71-
err = util.ResponseStream(c, orgRepo, cacheContent.Headers, bodyStreamChan)
72+
err = util.ResponseStream(context.Background(), c, orgRepo, cacheContent.Headers, bodyStreamChan, nil)
7273
if err != nil {
7374
return err
7475
}

internal/service/file_service.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func NewFileService(fileDao *dao.FileDao) *FileService {
3737
func (f *FileService) FileHeadCommon(c echo.Context, repoType, orgRepo, commit, filePath string) error {
3838
zap.S().Infof("exec file head:%s/%s/%s/%s, remoteAdd:%s", repoType, orgRepo, commit, filePath, c.Request().RemoteAddr)
3939
authorization := c.Request().Header.Get("authorization")
40-
commitSha, err := f.fileDao.GetFileCommitSha(repoType, orgRepo, commit, authorization)
40+
commitSha, err := f.fileDao.GetFileCommitSha(repoType, orgRepo, commit, authorization, "file")
4141
if err != nil {
4242
if e, ok := err.(myerr.Error); ok {
4343
return util.ErrorEntryUnknown(c, e.StatusCode(), e.Error())
@@ -50,7 +50,7 @@ func (f *FileService) FileHeadCommon(c echo.Context, repoType, orgRepo, commit,
5050
func (f *FileService) FileGetCommon(c echo.Context, repoType, orgRepo, commit, filePath string) error {
5151
zap.S().Infof("exec file get:%s/%s/%s/%s, remoteAdd:%s", repoType, orgRepo, commit, filePath, c.Request().RemoteAddr)
5252
authorization := c.Request().Header.Get("authorization")
53-
commitSha, err := f.fileDao.GetFileCommitSha(repoType, orgRepo, commit, authorization)
53+
commitSha, err := f.fileDao.GetFileCommitSha(repoType, orgRepo, commit, authorization, "file")
5454
if err != nil {
5555
if e, ok := err.(myerr.Error); ok {
5656
return util.ErrorEntryUnknown(c, e.StatusCode(), e.Error())

internal/service/meta_service.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
package service
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"io"
2021
"sort"
22+
"strings"
2123

2224
"dingospeed/internal/dao"
2325
"dingospeed/pkg/common"
@@ -103,7 +105,7 @@ func (m *MetaService) RepoRefs(c echo.Context, repoType, org, repo string) error
103105
var bodyStreamChan = make(chan []byte, consts.RespChanSize)
104106
bodyStreamChan <- cacheContent.OriginContent
105107
close(bodyStreamChan)
106-
return util.ResponseStream(c, orgRepo, cacheContent.Headers, bodyStreamChan)
108+
return util.ResponseStream(context.Background(), c, orgRepo, cacheContent.Headers, bodyStreamChan, nil)
107109
}
108110

109111
func (m *MetaService) ForwardToNewSite(c echo.Context) error {
@@ -114,9 +116,26 @@ func (m *MetaService) ForwardToNewSite(c echo.Context) error {
114116
return util.ErrorProxyError(c)
115117
}
116118
defer resp.Body.Close()
119+
120+
// 获取当前请求路径
121+
var flag bool
122+
reqPath := c.Request().URL.Path
123+
if strings.Contains(reqPath, "/tree/") && strings.Contains(reqPath, "/api/") {
124+
flag = true
125+
}
117126
response := c.Response()
118127
for k, v := range resp.Header {
119-
response.Header()[k] = v
128+
if flag && k == "Link" {
129+
originalLink := strings.Join(v, ", ")
130+
newLink := strings.ReplaceAll(
131+
originalLink,
132+
"https://huggingface.co",
133+
config.SysConfig.Scheduler.LinkDomain,
134+
)
135+
response.Header()[k] = []string{newLink}
136+
} else {
137+
response.Header()[k] = v
138+
}
120139
}
121140
response.WriteHeader(resp.StatusCode)
122141
_, err = io.Copy(response, resp.Body)

internal/service/task/preheat_cache_task.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,11 @@ func (p *PreheatCacheTask) startPreheat(hfUri, orgRepo, fileName, commit, etag,
140140
return p.result(ctx, responseChan)
141141
})
142142
eg.Go(func() error {
143-
p.DownloaderDao.FileDownload(offset, fileSize, false, taskParam)
143+
fileErrCh := make(chan error, 1)
144+
p.DownloaderDao.FileDownload(fileErrCh, offset, fileSize, false, taskParam)
145+
if err := <-fileErrCh; err != nil {
146+
return err
147+
}
144148
return nil
145149
})
146150
return eg.Wait()

0 commit comments

Comments
 (0)