gifs/api
2014-08-27
Child:eb450538f079
gifs/api/usage.go
Spike out functionality and tests. Create our interfaces around storing data and retrieving it. Create an in-memory implementation of our interfaces, for testing and rapid dev purposes. Begin sketching out what our unit tests look like. Create our Google Cloud Storage datastore implementation. Sketch out an idea for a usage collection process to keep track of which users are actually using stuff.
| paddy@0 | 1 package api |
| paddy@0 | 2 |
| paddy@0 | 3 import ( |
| paddy@0 | 4 "sync" |
| paddy@0 | 5 ) |
| paddy@0 | 6 |
| paddy@0 | 7 func NewUsageTracker() *UsageTracker { |
| paddy@0 | 8 return &UsageTracker{ |
| paddy@0 | 9 usages: make(map[string]*Usage), |
| paddy@0 | 10 } |
| paddy@0 | 11 } |
| paddy@0 | 12 |
| paddy@0 | 13 type UsageTracker struct { |
| paddy@0 | 14 usages map[string]*Usage |
| paddy@0 | 15 sync.Mutex |
| paddy@0 | 16 } |
| paddy@0 | 17 |
| paddy@0 | 18 func (u *UsageTracker) TrackUploads(id string) (bytes, requests chan int64) { |
| paddy@0 | 19 u.Lock() |
| paddy@0 | 20 defer u.Unlock() |
| paddy@0 | 21 if _, ok := u.usages[id]; !ok { |
| paddy@0 | 22 u.usages[id] = &Usage{ |
| paddy@0 | 23 UploadBytesChan: make(chan int64), |
| paddy@0 | 24 DownloadBytesChan: make(chan int64), |
| paddy@0 | 25 UploadRequestsChan: make(chan int64), |
| paddy@0 | 26 DownloadRequestsChan: make(chan int64), |
| paddy@0 | 27 } |
| paddy@0 | 28 go u.usages[id].collect() |
| paddy@0 | 29 } |
| paddy@0 | 30 return u.usages[id].UploadBytesChan, u.usages[id].UploadRequestsChan |
| paddy@0 | 31 } |
| paddy@0 | 32 |
| paddy@0 | 33 func (u *UsageTracker) TrackDownloads(id string) (bytes, requests chan int64) { |
| paddy@0 | 34 u.Lock() |
| paddy@0 | 35 defer u.Unlock() |
| paddy@0 | 36 if _, ok := u.usages[id]; !ok { |
| paddy@0 | 37 u.usages[id] = &Usage{ |
| paddy@0 | 38 UploadBytesChan: make(chan int64), |
| paddy@0 | 39 DownloadBytesChan: make(chan int64), |
| paddy@0 | 40 UploadRequestsChan: make(chan int64), |
| paddy@0 | 41 DownloadRequestsChan: make(chan int64), |
| paddy@0 | 42 } |
| paddy@0 | 43 go u.usages[id].collect() |
| paddy@0 | 44 } |
| paddy@0 | 45 return u.usages[id].DownloadBytesChan, u.usages[id].DownloadRequestsChan |
| paddy@0 | 46 } |
| paddy@0 | 47 |
| paddy@0 | 48 type Usage struct { |
| paddy@0 | 49 UploadedBytes int64 |
| paddy@0 | 50 UploadBytesChan chan int64 |
| paddy@0 | 51 DownloadedBytes int64 |
| paddy@0 | 52 DownloadBytesChan chan int64 |
| paddy@0 | 53 UploadRequests int64 |
| paddy@0 | 54 UploadRequestsChan chan int64 |
| paddy@0 | 55 DownloadRequests int64 |
| paddy@0 | 56 DownloadRequestsChan chan int64 |
| paddy@0 | 57 } |
| paddy@0 | 58 |
| paddy@0 | 59 func (u *Usage) collect() { |
| paddy@0 | 60 for { |
| paddy@0 | 61 select { |
| paddy@0 | 62 case b, ok := <-u.UploadBytesChan: |
| paddy@0 | 63 if !ok { |
| paddy@0 | 64 u.UploadBytesChan = nil |
| paddy@0 | 65 } |
| paddy@0 | 66 u.UploadedBytes += b |
| paddy@0 | 67 case r, ok := <-u.UploadRequestsChan: |
| paddy@0 | 68 if !ok { |
| paddy@0 | 69 u.UploadRequestsChan = nil |
| paddy@0 | 70 } |
| paddy@0 | 71 u.UploadRequests += r |
| paddy@0 | 72 case b, ok := <-u.DownloadBytesChan: |
| paddy@0 | 73 if !ok { |
| paddy@0 | 74 u.DownloadBytesChan = nil |
| paddy@0 | 75 } |
| paddy@0 | 76 u.DownloadedBytes += b |
| paddy@0 | 77 case r, ok := <-u.DownloadRequestsChan: |
| paddy@0 | 78 if !ok { |
| paddy@0 | 79 u.DownloadRequestsChan = nil |
| paddy@0 | 80 } |
| paddy@0 | 81 u.DownloadRequests += r |
| paddy@0 | 82 } |
| paddy@0 | 83 if u.UploadBytesChan == nil && u.UploadRequestsChan == nil && u.DownloadBytesChan == nil && u.DownloadRequestsChan == nil { |
| paddy@0 | 84 break |
| paddy@0 | 85 } |
| paddy@0 | 86 } |
| paddy@0 | 87 } |