196 lines
4.6 KiB
Go
196 lines
4.6 KiB
Go
package transmission
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/pyed/transmission"
|
|
)
|
|
|
|
// CachedClient wraps transmission client with caching
|
|
type CachedClient struct {
|
|
client *transmission.TransmissionClient
|
|
cache transmission.Torrents
|
|
cacheTime time.Time
|
|
cacheTTL time.Duration
|
|
cacheMutex sync.RWMutex
|
|
statsCache *transmission.Stats
|
|
statsTime time.Time
|
|
statsMutex sync.RWMutex
|
|
}
|
|
|
|
// NewCachedClient creates a new cached transmission client
|
|
func NewCachedClient(client *transmission.TransmissionClient, cacheTTL time.Duration) *CachedClient {
|
|
return &CachedClient{
|
|
client: client,
|
|
cacheTTL: cacheTTL,
|
|
}
|
|
}
|
|
|
|
// GetTorrents returns cached torrents if available, otherwise fetches from API
|
|
func (c *CachedClient) GetTorrents() (transmission.Torrents, error) {
|
|
c.cacheMutex.RLock()
|
|
if time.Since(c.cacheTime) < c.cacheTTL && c.cache != nil {
|
|
torrents := c.cache
|
|
c.cacheMutex.RUnlock()
|
|
return torrents, nil
|
|
}
|
|
c.cacheMutex.RUnlock()
|
|
|
|
c.cacheMutex.Lock()
|
|
defer c.cacheMutex.Unlock()
|
|
|
|
// Double check after acquiring write lock
|
|
if time.Since(c.cacheTime) < c.cacheTTL && c.cache != nil {
|
|
return c.cache, nil
|
|
}
|
|
|
|
torrents, err := c.client.GetTorrents()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c.cache = torrents
|
|
c.cacheTime = time.Now()
|
|
return torrents, nil
|
|
}
|
|
|
|
// GetTorrent gets a single torrent (not cached)
|
|
func (c *CachedClient) GetTorrent(id int) (*transmission.Torrent, error) {
|
|
return c.client.GetTorrent(id)
|
|
}
|
|
|
|
// GetStats returns cached stats if available, otherwise fetches from API
|
|
func (c *CachedClient) GetStats() (*transmission.Stats, error) {
|
|
c.statsMutex.RLock()
|
|
if time.Since(c.statsTime) < c.cacheTTL && c.statsCache != nil {
|
|
stats := c.statsCache
|
|
c.statsMutex.RUnlock()
|
|
return stats, nil
|
|
}
|
|
c.statsMutex.RUnlock()
|
|
|
|
c.statsMutex.Lock()
|
|
defer c.statsMutex.Unlock()
|
|
|
|
// Double check after acquiring write lock
|
|
if time.Since(c.statsTime) < c.cacheTTL && c.statsCache != nil {
|
|
return c.statsCache, nil
|
|
}
|
|
|
|
stats, err := c.client.GetStats()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c.statsCache = stats
|
|
c.statsTime = time.Now()
|
|
return stats, nil
|
|
}
|
|
|
|
// InvalidateCache clears the cache
|
|
func (c *CachedClient) InvalidateCache() {
|
|
c.cacheMutex.Lock()
|
|
c.cache = nil
|
|
c.cacheTime = time.Time{}
|
|
c.cacheMutex.Unlock()
|
|
|
|
c.statsMutex.Lock()
|
|
c.statsCache = nil
|
|
c.statsTime = time.Time{}
|
|
c.statsMutex.Unlock()
|
|
}
|
|
|
|
// StopAll stops all torrents and invalidates cache
|
|
func (c *CachedClient) StopAll() error {
|
|
err := c.client.StopAll()
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return err
|
|
}
|
|
|
|
// StartAll starts all torrents and invalidates cache
|
|
func (c *CachedClient) StartAll() error {
|
|
err := c.client.StartAll()
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return err
|
|
}
|
|
|
|
// VerifyAll verifies all torrents and invalidates cache
|
|
func (c *CachedClient) VerifyAll() error {
|
|
err := c.client.VerifyAll()
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return err
|
|
}
|
|
|
|
// StopTorrent stops a torrent and invalidates cache
|
|
func (c *CachedClient) StopTorrent(id int) (string, error) {
|
|
status, err := c.client.StopTorrent(id)
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return status, err
|
|
}
|
|
|
|
// StartTorrent starts a torrent and invalidates cache
|
|
func (c *CachedClient) StartTorrent(id int) (string, error) {
|
|
status, err := c.client.StartTorrent(id)
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return status, err
|
|
}
|
|
|
|
// VerifyTorrent verifies a torrent and invalidates cache
|
|
func (c *CachedClient) VerifyTorrent(id int) (string, error) {
|
|
status, err := c.client.VerifyTorrent(id)
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return status, err
|
|
}
|
|
|
|
// DeleteTorrent deletes a torrent and invalidates cache
|
|
func (c *CachedClient) DeleteTorrent(id int, deleteData bool) (string, error) {
|
|
name, err := c.client.DeleteTorrent(id, deleteData)
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return name, err
|
|
}
|
|
|
|
// ExecuteCommand executes a command and invalidates cache
|
|
func (c *CachedClient) ExecuteCommand(cmd transmission.Command) (*transmission.CommandResult, error) {
|
|
result, err := c.client.ExecuteCommand(cmd)
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
// ExecuteAddCommand executes an add command and invalidates cache
|
|
func (c *CachedClient) ExecuteAddCommand(cmd transmission.AddCommand) (*transmission.Torrent, error) {
|
|
torrent, err := c.client.ExecuteAddCommand(cmd)
|
|
if err == nil {
|
|
c.InvalidateCache()
|
|
}
|
|
return torrent, err
|
|
}
|
|
|
|
// SetSort sets sort type and invalidates cache since it changes the order
|
|
func (c *CachedClient) SetSort(sort transmission.SortType) {
|
|
c.client.SetSort(sort)
|
|
c.InvalidateCache()
|
|
}
|
|
|
|
// Version returns transmission version
|
|
func (c *CachedClient) Version() string {
|
|
return c.client.Version()
|
|
}
|
|
|