From 107ec1dd153786c000d7a7271bfcde85eae7f301 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Mon, 26 Aug 2013 14:38:45 -0400 Subject: [PATCH] more work towards new architecture --- cache/cache.go | 14 +++++------ cache/redis/redis.go | 8 +++---- config/config.go | 18 +++++++------- config/config_test.go | 15 ++++++++---- server/announce.go | 2 +- storage/storage.go | 55 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 storage/storage.go diff --git a/cache/cache.go b/cache/cache.go index 8ead108..85470c3 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -2,7 +2,7 @@ // Use of this source code is governed by the BSD 2-Clause license, // which can be found in the LICENSE file. -// Package storage provides a generic interface for manipulating a +// Package cache provides a generic interface for manipulating a // BitTorrent tracker's fast moving data. package cache @@ -16,11 +16,11 @@ import ( var ( drivers = make(map[string]Driver) - ErrTxDone = errors.New("storage: Transaction has already been committed or rolled back") + ErrTxDone = errors.New("cache: Transaction has already been committed or rolled back") ) type Driver interface { - New(*config.Cache) Pool + New(*config.DataStore) Pool } // Register makes a database driver available by the provided name. @@ -28,20 +28,20 @@ type Driver interface { // it panics. func Register(name string, driver Driver) { if driver == nil { - panic("storage: Register driver is nil") + panic("cache: Register driver is nil") } if _, dup := drivers[name]; dup { - panic("storage: Register called twice for driver " + name) + panic("cache: Register called twice for driver " + name) } drivers[name] = driver } // Open creates a pool of data store connections specified by a storage configuration. -func Open(conf *config.Cache) (Pool, error) { +func Open(conf *config.DataStore) (Pool, error) { driver, ok := drivers[conf.Driver] if !ok { return nil, fmt.Errorf( - "storage: unknown driver %q (forgotten import?)", + "cache: unknown driver %q (forgotten import?)", conf.Driver, ) } diff --git a/cache/redis/redis.go b/cache/redis/redis.go index bd09fab..d87f451 100644 --- a/cache/redis/redis.go +++ b/cache/redis/redis.go @@ -27,7 +27,7 @@ import ( type driver struct{} -func (d *driver) New(conf *config.Cache) cache.Pool { +func (d *driver) New(conf *config.DataStore) cache.Pool { return &Pool{ conf: conf, pool: redis.Pool{ @@ -39,7 +39,7 @@ func (d *driver) New(conf *config.Cache) cache.Pool { } } -func makeDialFunc(conf *config.Cache) func() (redis.Conn, error) { +func makeDialFunc(conf *config.DataStore) func() (redis.Conn, error) { return func() (conn redis.Conn, err error) { conn, err = redis.Dial(conf.Network, conf.Addr) if err != nil { @@ -55,7 +55,7 @@ func testOnBorrow(c redis.Conn, t time.Time) error { } type Pool struct { - conf *config.Cache + conf *config.DataStore pool redis.Pool } @@ -87,7 +87,7 @@ func (p *Pool) Get() (cache.Tx, error) { // SET keyB // EXEC type Tx struct { - conf *config.Cache + conf *config.DataStore done bool multi bool redis.Conn diff --git a/config/config.go b/config/config.go index 8f417be..24b06ea 100644 --- a/config/config.go +++ b/config/config.go @@ -27,8 +27,8 @@ func (d *Duration) UnmarshalJSON(b []byte) error { return err } -// Cache represents the configuration for any data store used as a cache. -type Cache struct { +// DataStore represents the configuration used to connect to a data store. +type DataStore struct { Driver string `json:"driver"` Network string `json:"network` Addr string `json:"addr"` @@ -38,16 +38,16 @@ type Cache struct { Encoding string `json:"encoding,omitempty"` Prefix string `json:"prefix,omitempty"` - MaxIdleConn int `json:"max_idle_conn"` - IdleTimeout *Duration `json:"idle_timeout"` - TxRetries int `json:"tx_retries"` + MaxIdleConn int `json:"max_idle_conn,omitempty"` + IdleTimeout *Duration `json:"idle_timeout,omitempty"` } // Config represents a configuration for a server.Server. type Config struct { - Addr string `json:"addr"` - PubAddr string `json:"pub_addr"` - Cache Cache `json:"cache"` + Addr string `json:"addr"` + PubAddr string `json:"pub_addr"` + Cache DataStore `json:"cache"` + Storage DataStore `json:"storage"` Private bool `json:"private"` Freeleech bool `json:"freeleech"` @@ -57,6 +57,8 @@ type Config struct { MinAnnounce Duration `json:"min_announce"` ReadTimeout Duration `json:"read_timeout"` DefaultNumWant int `json:"default_num_want"` + + TxRetries int `json:"tx_retries"` } // Open is a shortcut to open a file, read it, and generate a Config. diff --git a/config/config_test.go b/config/config_test.go index 99a85d1..e5bb22c 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -17,6 +17,7 @@ var exampleJson = `{ "network": "tcp", "addr": ":34000", "pub_addr": "tcp://*:34001", + "cache": { "driver": "redis", "addr": "127.0.0.1:6379", @@ -25,9 +26,14 @@ var exampleJson = `{ "prefix": "test:", "max_idle_conn": 3, - "idle_timeout": "240s", - "conn_timeout": "5s", - "tx_retries": 3 + "idle_timeout": "240s" + }, + + "storage": { + "driver": "batter", + "addr": "127.0.0.1:5432", + "user": "postgres", + "pass": "" }, "private": true, @@ -36,8 +42,9 @@ var exampleJson = `{ "announce": "30m", "min_announce": "15m", "read_timeout": "20s", - "default_num_want": 50 + "default_num_want": 50, + "tx_retries": 3 }` func TestNewConfig(t *testing.T) { diff --git a/server/announce.go b/server/announce.go index 50ca482..1d7a142 100644 --- a/server/announce.go +++ b/server/announce.go @@ -24,7 +24,7 @@ func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) { } // Retry failed transactions a specified number of times - for i := 0; i < s.conf.Cache.TxRetries; i++ { + for i := 0; i < s.conf.TxRetries; i++ { // Start a transaction tx, err := s.dbConnPool.Get() diff --git a/storage/storage.go b/storage/storage.go new file mode 100644 index 0000000..10109c0 --- /dev/null +++ b/storage/storage.go @@ -0,0 +1,55 @@ +// Copyright 2013 The Chihaya Authors. All rights reserved. +// Use of this source code is governed by the BSD 2-Clause license, +// which can be found in the LICENSE file. + +// Package storage provides a generic interface for manipulating a +// BitTorrent tracker's web application data. +package storage + +import ( + "fmt" + + "github.com/pushrax/chihaya/config" + "github.com/pushrax/chihaya/models" +) + +var ( + drivers = make(map[string]Driver) +) + +type Driver interface { + New(*config.DataStore) Conn +} + +// Register makes a database driver available by the provided name. +// If Register is called twice with the same name or if driver is nil, +// it panics. +func Register(name string, driver Driver) { + if driver == nil { + panic("storage: Register driver is nil") + } + if _, dup := drivers[name]; dup { + panic("storage: Register called twice for driver " + name) + } + drivers[name] = driver +} + +// Open creates a connection specified by a storage configuration. +func Open(conf *config.DataStore) (Conn, error) { + driver, ok := drivers[conf.Driver] + if !ok { + return nil, fmt.Errorf( + "storage: unknown driver %q (forgotten import?)", + conf.Driver, + ) + } + pool := driver.New(conf) + return pool, nil +} + +// Conn represents a connection to the data store. +type Conn interface { + Close() error + UpdateTorrents(t []models.Torrent) error + UpdateUsers(u []models.User) error +}