Skip to content

Commit c1e1f96

Browse files
authored
feat: optimize torrent list API with lightweight status and filtering (#693)
1 parent 83900e7 commit c1e1f96

3 files changed

Lines changed: 104 additions & 4 deletions

File tree

server/torr/apihelper.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,32 @@ func ListTorrent() []*Torrent {
206206
return ret
207207
}
208208

209+
func ListTorrentFiltered(filter string) []*Torrent {
210+
switch filter {
211+
case "last":
212+
all := ListTorrent()
213+
if len(all) > 0 {
214+
return all[:1]
215+
}
216+
return nil
217+
case "active":
218+
btlist := bts.ListTorrents()
219+
var ret []*Torrent
220+
for _, t := range btlist {
221+
ret = append(ret, t)
222+
}
223+
sort.Slice(ret, func(i, j int) bool {
224+
if ret[i].Timestamp != ret[j].Timestamp {
225+
return ret[i].Timestamp > ret[j].Timestamp
226+
}
227+
return ret[i].Title > ret[j].Title
228+
})
229+
return ret
230+
default:
231+
return ListTorrent()
232+
}
233+
}
234+
209235
func DropTorrent(hashHex string) {
210236
hash := metainfo.NewHashFromHex(hashHex)
211237
bts.RemoveTorrent(hash)

server/torr/torrent.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,45 @@ func (t *Torrent) Status() *state.TorrentStatus {
385385
return st
386386
}
387387

388+
func (t *Torrent) StatusLight() *state.TorrentStatus {
389+
t.muTorrent.Lock()
390+
defer t.muTorrent.Unlock()
391+
392+
st := new(state.TorrentStatus)
393+
394+
st.Stat = t.Stat
395+
st.StatString = t.Stat.String()
396+
st.Title = t.Title
397+
st.Category = t.Category
398+
st.Poster = t.Poster
399+
st.Data = t.Data
400+
st.Timestamp = t.Timestamp
401+
st.TorrentSize = t.Size
402+
st.BitRate = t.BitRate
403+
st.DurationSeconds = t.DurationSeconds
404+
405+
if t.TorrentSpec != nil {
406+
st.Hash = t.TorrentSpec.InfoHash.HexString()
407+
}
408+
if t.Torrent != nil {
409+
st.Name = t.Torrent.Name()
410+
st.Hash = t.Torrent.InfoHash().HexString()
411+
st.DownloadSpeed = t.DownloadSpeed
412+
st.UploadSpeed = t.UploadSpeed
413+
414+
tst := t.Torrent.Stats()
415+
st.TotalPeers = tst.TotalPeers
416+
st.ActivePeers = tst.ActivePeers
417+
st.ConnectedSeeders = tst.ConnectedSeeders
418+
419+
if t.Torrent.Info() != nil {
420+
st.TorrentSize = t.Torrent.Length()
421+
}
422+
}
423+
424+
return st
425+
}
426+
388427
func (t *Torrent) CacheState() *cacheSt.CacheState {
389428
if t.Torrent != nil && t.cache != nil {
390429
st := t.cache.GetState()

server/web/api/torrents.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"net/http"
55
"server/torrshash"
66
"strings"
7+
"sync"
8+
"time"
79

810
"server/dlna"
911
"server/log"
@@ -27,8 +29,16 @@ type torrReqJS struct {
2729
Poster string `json:"poster,omitempty"`
2830
Data string `json:"data,omitempty"`
2931
SaveToDB bool `json:"save_to_db,omitempty"`
32+
Filter string `json:"filter,omitempty"`
3033
}
3134

35+
var (
36+
listCache []*state.TorrentStatus
37+
listCacheTime time.Time
38+
listCacheMu sync.Mutex
39+
listCacheTTL = 2 * time.Second
40+
)
41+
3242
// torrents godoc
3343
//
3444
// @Summary Handle torrents informations
@@ -69,7 +79,7 @@ func torrents(c *gin.Context) {
6979
}
7080
case "list":
7181
{
72-
listTorrents(c)
82+
listTorrents(c, req.Filter)
7383
}
7484
case "drop":
7585
{
@@ -193,16 +203,41 @@ func remTorrent(req torrReqJS, c *gin.Context) {
193203
c.Status(200)
194204
}
195205

196-
func listTorrents(c *gin.Context) {
197-
list := torr.ListTorrent()
206+
func listTorrents(c *gin.Context, filter string) {
207+
if filter == "" {
208+
filter = "all"
209+
}
210+
211+
// Return cached response for "all" filter if fresh enough
212+
if filter == "all" {
213+
listCacheMu.Lock()
214+
if listCache != nil && time.Since(listCacheTime) < listCacheTTL {
215+
cached := listCache
216+
listCacheMu.Unlock()
217+
c.JSON(200, cached)
218+
return
219+
}
220+
listCacheMu.Unlock()
221+
}
222+
223+
list := torr.ListTorrentFiltered(filter)
198224
if len(list) == 0 {
199225
c.JSON(200, []*state.TorrentStatus{})
200226
return
201227
}
202228
var stats []*state.TorrentStatus
203229
for _, tr := range list {
204-
stats = append(stats, tr.Status())
230+
stats = append(stats, tr.StatusLight())
205231
}
232+
233+
// Cache "all" results
234+
if filter == "all" {
235+
listCacheMu.Lock()
236+
listCache = stats
237+
listCacheTime = time.Now()
238+
listCacheMu.Unlock()
239+
}
240+
206241
c.JSON(200, stats)
207242
}
208243

0 commit comments

Comments
 (0)