github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/api/client/downloader.go (about) 1 package client 2 3 import ( 4 "bytes" 5 6 "github.com/hoffie/larasync/repository" 7 "github.com/hoffie/larasync/repository/nib" 8 ) 9 10 // Downloader returns the downloader configured for the client 11 // and the passed ClientRepository. 12 func (c *Client) Downloader(r *repository.ClientRepository) *Downloader { 13 return &Downloader{ 14 client: c, 15 r: r, 16 } 17 } 18 19 // Downloader handles downloads from server to client 20 type Downloader struct { 21 client *Client 22 r *repository.ClientRepository 23 } 24 25 // GetAll ensures that the local state matches the remote state. 26 func (dl *Downloader) GetAll() error { 27 err := dl.getNIBs() 28 if err != nil { 29 return err 30 } 31 return nil 32 } 33 34 // GetDelta ensures that all data from the last synced transaction 35 // is in sync with the local one. 36 func (dl *Downloader) GetDelta() error { 37 repository := dl.r 38 stateConfig, err := repository.StateConfig() 39 if err != nil { 40 return err 41 } 42 defaultServer := stateConfig.DefaultServer 43 remoteTransactionID := defaultServer.RemoteTransactionID 44 if remoteTransactionID == 0 { 45 err = dl.getNIBs() 46 } else { 47 err = dl.getFromServerTransactionID(defaultServer.RemoteTransactionID) 48 } 49 return err 50 } 51 52 // getFromServerTransactionID syncs all data from the given server transaction 53 // ID. 54 func (dl *Downloader) getFromServerTransactionID(transactionID int64) error { 55 nibResponse, err := dl.client.GetNIBsFromTransactionID(transactionID) 56 if err != nil { 57 return err 58 } 59 return dl.processNIBResponse(nibResponse) 60 } 61 62 // getNIBs downloads all NIBs and stores them in the repository 63 func (dl *Downloader) getNIBs() error { 64 nibResponse, err := dl.client.GetNIBs() 65 if err != nil { 66 return err 67 } 68 return dl.processNIBResponse(nibResponse) 69 } 70 71 // processNIBResponse synchronizes the given NIBResponse to the local client state. 72 func (dl *Downloader) processNIBResponse(response *NIBGetResponse) error { 73 err := dl.processNIBBytes(response.NIBData) 74 if err != nil { 75 return err 76 } 77 serverTransaction := response.ServerTransactionID 78 stateConfig, err := dl.r.StateConfig() 79 if err != nil { 80 return err 81 } 82 stateConfig.DefaultServer.RemoteTransactionID = serverTransaction 83 return stateConfig.Save() 84 } 85 86 // processNibBytes parses a channel and adds the NIBs being represented by each 87 // passed byte array. 88 func (dl *Downloader) processNIBBytes(nibBytesIterator <-chan []byte) error { 89 for nibBytes := range nibBytesIterator { 90 // FIXME: overwrite checking! 91 n, err := dl.r.VerifyAndParseNIBBytes(nibBytes) 92 if err != nil { 93 return err 94 } 95 err = dl.fetchMissingData(n) 96 if err != nil { 97 return err 98 } 99 100 err = dl.r.AddNIBContent(bytes.NewReader(nibBytes)) 101 if err != nil { 102 return err 103 } 104 } 105 return nil 106 } 107 108 // fetchMissingData loads missing objects in the passed NIB. 109 func (dl *Downloader) fetchMissingData(n *nib.NIB) error { 110 objectIDs := n.AllObjectIDs() 111 for _, objectID := range objectIDs { 112 if dl.r.HasObject(objectID) { 113 continue 114 } 115 err := dl.getObject(objectID) 116 if err != nil { 117 return err 118 } 119 } 120 return nil 121 } 122 123 // getObject downloads the named object 124 func (dl *Downloader) getObject(objectID string) error { 125 resp, err := dl.client.GetObject(objectID) 126 if err != nil { 127 return err 128 } 129 err = dl.r.AddObject(objectID, resp) 130 return err 131 }