11package service
22
33import (
4+ "context"
45 "dacapo/backend/model"
56 "dacapo/backend/utils"
67 "errors"
78 "fmt"
9+ "io"
810 "io/fs"
11+ "net/http"
912 "os"
1013 "path/filepath"
1114 "time"
@@ -177,6 +180,50 @@ func (s *InstanceUpdaterService) getVenvPython(envName string) string {
177180 return ""
178181}
179182
183+ // getPyPIMirror returns the fastest available PyPI mirror URL
184+ func getPyPIMirror () (string , error ) {
185+ mirrors := map [string ]string {
186+ "https://pypi.tuna.tsinghua.edu.cn/simple" : "https://pypi.tuna.tsinghua.edu.cn/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl" ,
187+ "https://mirrors.aliyun.com/pypi/simple" : "https://mirrors.aliyun.com/pypi/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl" ,
188+ "https://pypi.mirrors.ustc.edu.cn/simple" : "https://mirrors.ustc.edu.cn/pypi/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl" ,
189+ "https://pypi.org/simple" : "https://files.pythonhosted.org/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl" ,
190+ }
191+
192+ ctx , cancel := context .WithTimeout (context .Background (), 30 * time .Second )
193+ defer cancel ()
194+
195+ resultChan := make (chan string , 1 )
196+
197+ for mirror , url := range mirrors {
198+ go func () {
199+ req , _ := http .NewRequestWithContext (ctx , "GET" , url , nil )
200+
201+ resp , err := http .DefaultClient .Do (req )
202+ if err != nil {
203+ return
204+ }
205+ defer resp .Body .Close ()
206+
207+ if _ , err := io .Copy (io .Discard , resp .Body ); err != nil {
208+ return
209+ }
210+
211+ select {
212+ case resultChan <- mirror :
213+ default :
214+ }
215+ }()
216+ }
217+
218+ select {
219+ case fastest := <- resultChan :
220+ cancel () // Cancel other ongoing downloads when first mirror completes
221+ return fastest , nil
222+ case <- ctx .Done ():
223+ return "" , fmt .Errorf ("network too slow, unable to download Python packages, please try again later" )
224+ }
225+ }
226+
180227// installDeps installs Python dependencies
181228func (s * InstanceUpdaterService ) installDeps (tm * model.TaskManager , envPath , depsPath string , envLastUpdate time.Time ) error {
182229 // Check if requirements file exists
@@ -196,17 +243,21 @@ func (s *InstanceUpdaterService) installDeps(tm *model.TaskManager, envPath, dep
196243
197244 uvPath := "./tools/uv.exe"
198245 var cmd string
246+ fastestMirror , err := getPyPIMirror ()
247+ if err != nil {
248+ return err
249+ }
199250
200251 if _ , err := os .Stat (uvPath ); err == nil {
201- cmd = fmt .Sprintf ("%s pip install -r %s --python %s -i https://pypi.tuna.tsinghua.edu.cn/simple/ " ,
202- uvPath , depsPath , envPath )
252+ cmd = fmt .Sprintf ("%s pip install -r %s --python %s -i %s " ,
253+ uvPath , depsPath , envPath , fastestMirror )
203254 utils .Logger .Infof ("[%s]: Installing dependencies with uv: %s" , tm .InstanceName , cmd )
204255 } else {
205256 pythonExec := s .getVenvPython (filepath .Base (envPath ))
206257 if pythonExec == "" {
207258 return fmt .Errorf ("python not found in %s" , envPath )
208259 }
209- cmd = pythonExec + " -m pip install -r " + depsPath + " -i https://pypi.tuna.tsinghua.edu.cn/simple/"
260+ cmd = pythonExec + " -m pip install -r " + depsPath + " -i " + fastestMirror
210261 utils .Logger .Infof ("[%s]: Installing dependencies with pip: %s" , tm .InstanceName , cmd )
211262 }
212263
0 commit comments