Files
transmission-telegram/internal/transmission/client.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.Command, 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.Command) (transmission.TorrentAdded, 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.Sorting) {
c.client.SetSort(sort)
c.InvalidateCache()
}
// Version returns transmission version
func (c *CachedClient) Version() string {
return c.client.Version()
}