feat: add batch create and server info APIs (#540)

This commit is contained in:
Levi authored and GitHub committed 2024-05-17 15:19:10 +08:00
1 parent 42a0b89d95
commit 68c40d7f3f
8 files changed
+112 -8

No files matched your search

+12
View File
@@ -301,6 +301,18 @@ func (d *Downloader) CreateDirect(req *base.Request, opts *base.Options) (taskId
return d.doCreate(fetcher, opts)
}
func (d *Downloader) CreateDirectBatch(reqs []*base.Request, opts *base.Options) (taskId []string, err error) {
taskIds := make([]string, 0)
for _, req := range reqs {
taskId, err := d.CreateDirect(req, opts)
if err != nil {
return nil, err
}
taskIds = append(taskIds, taskId)
}
return taskIds, nil
}
func (d *Downloader) Create(rrId string, opts *base.Options) (taskId string, err error) {
d.fetcherMapLock.RLock()
fetcher, ok := d.fetcherCache[rrId]
+35
View File
@@ -84,6 +84,41 @@ func TestDownloader_Create(t *testing.T) {
}
}
func TestDownloader_CreateDirectBatch(t *testing.T) {
listener := test.StartTestFileServer()
defer listener.Close()
downloader := NewDownloader(nil)
if err := downloader.Setup(); err != nil {
t.Fatal(err)
}
defer downloader.Clear()
reqs := make([]*base.Request, 0)
for i := 0; i < 6; i++ {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
reqs = append(reqs, req)
}
_, err := downloader.CreateDirectBatch(reqs, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
if err != nil {
t.Fatal(err)
}
tasks := downloader.GetTasks()
if len(tasks) != len(reqs) {
t.Errorf("CreateDirectBatch() got = %v, want %v", len(tasks), len(reqs))
}
}
func TestDownloader_CreateWithProxy(t *testing.T) {
// No proxy
doTestDownloaderCreateWithProxy(t, false, func(proxyCfg *base.DownloaderProxyConfig) *base.DownloaderProxyConfig {
+3 -1
View File
@@ -69,7 +69,9 @@ func (n *MemStorage) Setup(buckets []string) error {
func (n *MemStorage) Put(bucket string, key string, v any) error {
n.lock.Lock()
defer n.lock.Unlock()
memData[bucket][key] = v
if bucketData, ok := memData[bucket]; ok {
bucketData[key] = v
}
return nil
}
+28
View File
@@ -8,8 +8,20 @@ import (
"io"
"net/http"
"net/url"
"runtime"
)
func Info(w http.ResponseWriter, r *http.Request) {
info := map[string]any{
"version": base.Version,
"runtime": runtime.Version(),
"os": runtime.GOOS,
"arch": runtime.GOARCH,
}
info["inDocker"] = base.InDocker == "true"
WriteJson(w, model.NewOkResult(info))
}
func Resolve(w http.ResponseWriter, r *http.Request) {
var req base.Request
if ReadJson(r, w, &req) {
@@ -45,6 +57,22 @@ func CreateTask(w http.ResponseWriter, r *http.Request) {
}
}
func CreateTaskBatch(w http.ResponseWriter, r *http.Request) {
var req model.CreateTaskBatch
if ReadJson(r, w, &req) {
if len(req.Reqs) == 0 {
WriteJson(w, model.NewErrorResult("param invalid: reqs", model.CodeInvalidParam))
return
}
taskIds, err := Downloader.CreateDirectBatch(req.Reqs, req.Opt)
if err != nil {
WriteJson(w, model.NewErrorResult(err.Error()))
return
}
WriteJson(w, model.NewOkResult(taskIds))
}
}
func PauseTask(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
taskId := vars["id"]
-7
View File
@@ -1,7 +0,0 @@
package model
type Command struct {
Protocol string `json:"protocol"`
Action string `json:"action"`
Params any `json:"params"`
}
+5
View File
@@ -7,3 +7,8 @@ type CreateTask struct {
Req *base.Request `json:"req"`
Opt *base.Options `json:"opt"`
}
type CreateTaskBatch struct {
Reqs []*base.Request `json:"reqs"`
Opt *base.Options `json:"opt"`
}
+2
View File
@@ -88,8 +88,10 @@ func BuildServer(startCfg *model.StartConfig) (*http.Server, net.Listener, error
}
var r = mux.NewRouter()
r.Methods(http.MethodGet).Path("/api/v1/info").HandlerFunc(Info)
r.Methods(http.MethodPost).Path("/api/v1/resolve").HandlerFunc(Resolve)
r.Methods(http.MethodPost).Path("/api/v1/tasks").HandlerFunc(CreateTask)
r.Methods(http.MethodPost).Path("/api/v1/tasks/batch").HandlerFunc(CreateTaskBatch)
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/pause").HandlerFunc(PauseTask)
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/continue").HandlerFunc(ContinueTask)
r.Methods(http.MethodPut).Path("/api/v1/tasks/pause").HandlerFunc(PauseAllTask)
+27
View File
@@ -63,6 +63,18 @@ var (
}
)
func TestInfo(t *testing.T) {
matchKeys := []string{"version", "runtime", "os", "arch", "inDocker"}
doTest(func() {
resp := httpRequestCheckOk[map[string]any](http.MethodGet, "/api/v1/info", nil)
for _, key := range matchKeys {
if _, ok := resp[key]; !ok {
t.Errorf("Info() missing key = %v", key)
}
}
})
}
func TestResolve(t *testing.T) {
doTest(func() {
resp := httpRequestCheckOk[*download.ResolveResult](http.MethodPost, "/api/v1/resolve", taskReq)
@@ -125,6 +137,21 @@ func TestCreateDirectTask(t *testing.T) {
})
}
func TestCreateDirectTaskBatch(t *testing.T) {
doTest(func() {
reqs := make([]*base.Request, 0)
for i := 0; i < 6; i++ {
reqs = append(reqs, createReq.Req)
}
taskIds := httpRequestCheckOk[[]string](http.MethodPost, "/api/v1/tasks/batch", &model.CreateTaskBatch{
Reqs: reqs,
})
if len(taskIds) != len(reqs) {
t.Errorf("CreateDirectTaskBatch() got = %v, want %v", len(taskIds), len(reqs))
}
})
}
func TestCreateDirectTaskWithResoled(t *testing.T) {
doTest(func() {
var wg sync.WaitGroup