github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/api/client/uploader.go (about) 1 package client 2 3 import ( 4 "fmt" 5 6 "github.com/hoffie/larasync/repository" 7 "github.com/hoffie/larasync/repository/nib" 8 ) 9 10 // Uploader returns the uploader for the given client in the passed 11 // repository. 12 func (c *Client) Uploader(r *repository.ClientRepository) *Uploader { 13 return &Uploader{ 14 client: c, 15 r: r, 16 } 17 } 18 19 // Uploader handles uploads from server to client 20 type Uploader struct { 21 client *Client 22 r *repository.ClientRepository 23 } 24 25 // PushAll ensures that the remote state is synced with the local state. 26 func (ul *Uploader) PushAll() error { 27 r := ul.r 28 transaction, err := r.CurrentTransaction() 29 if err != nil { 30 return err 31 } 32 err = ul.uploadNIBs() 33 if err != nil { 34 return err 35 } 36 return ul.saveLastUploadedTransaction(transaction) 37 } 38 39 // PushDelta pushes all nibs from the stored local transaction id. 40 func (ul *Uploader) PushDelta() error { 41 r := ul.r 42 s, err := r.StateConfig() 43 if err != nil { 44 return err 45 } 46 47 defaultServer := s.DefaultServer 48 if defaultServer.LocalTransactionID != 0 { 49 err = ul.pushFromTransactionID(defaultServer.LocalTransactionID) 50 } else { 51 err = ul.PushAll() 52 } 53 return err 54 } 55 56 // PushFromTransactionID pushes all NIBs which have been entered after 57 // the given local transaction ID. 58 func (ul *Uploader) pushFromTransactionID(transactionID int64) error { 59 r := ul.r 60 transactions, err := r.TransactionsFrom(transactionID) 61 if err != nil { 62 return fmt.Errorf("unable to get transactions (%s)", err) 63 } 64 65 var lastTransaction *repository.Transaction 66 for _, transaction := range transactions { 67 err = ul.uploadTransaction(transaction) 68 if err != nil { 69 return err 70 } 71 lastTransaction = transaction 72 } 73 74 if lastTransaction != nil { 75 err = ul.saveLastUploadedTransaction(lastTransaction) 76 if err != nil { 77 return err 78 } 79 } 80 81 return nil 82 } 83 84 // saveLastUploadedTransaction takes the given transaction and configures it to the 85 // state config to store it as the last transaction. 86 func (ul *Uploader) saveLastUploadedTransaction(transaction *repository.Transaction) error { 87 r := ul.r 88 s, err := r.StateConfig() 89 if err != nil { 90 return nil 91 } 92 s.DefaultServer.LocalTransactionID = transaction.ID 93 err = s.Save() 94 if err != nil { 95 return err 96 } 97 return nil 98 } 99 100 // uploadTransaction uploads all nibs in the added transaction. 101 func (ul *Uploader) uploadTransaction(transaction *repository.Transaction) error { 102 r := ul.r 103 for _, nibID := range transaction.NIBIDs { 104 nib, err := r.GetNIB(nibID) 105 if err != nil { 106 return fmt.Errorf("could not load NIB with id %s (%s)", nibID, err) 107 } 108 err = ul.uploadNIB(nib) 109 if err != nil { 110 return err 111 } 112 } 113 return nil 114 } 115 116 // uploadNIBs uploads all local NIBs and content of the NIBs to 117 // the server. 118 func (ul *Uploader) uploadNIBs() error { 119 r := ul.r 120 nibs, err := r.GetAllNibs() 121 if err != nil { 122 return fmt.Errorf("unable to get NIB list (%s)", err) 123 } 124 125 for n := range nibs { 126 err = ul.uploadNIB(n) 127 if err != nil { 128 return err 129 } 130 } 131 132 return nil 133 } 134 135 // uploadNIB uploads a single passed NIB to the remote server. 136 func (ul *Uploader) uploadNIB(n *nib.NIB) error { 137 r := ul.r 138 client := ul.client 139 Log.Debug(fmt.Sprintf("Uploading nib with ID %s", n.ID)) 140 nibReader, err := r.GetNIBReader(n.ID) 141 if err != nil { 142 return err 143 } 144 defer nibReader.Close() 145 146 err = client.PutNIB(n.ID, nibReader) 147 var objectIDs []string 148 if err == nil { 149 return nil 150 } 151 if !repository.IsNIBContentMissing(err) { 152 return fmt.Errorf("uploading nib %s failed (%s)", n.ID, err) 153 } 154 nibContentMissing := err.(*repository.ErrNIBContentMissing) 155 objectIDs = nibContentMissing.MissingContentIDs() 156 for _, objectID := range objectIDs { 157 err = ul.uploadObject(objectID) 158 if err != nil { 159 return err 160 } 161 } 162 nibReader, err = r.GetNIBReader(n.ID) 163 if err != nil { 164 return err 165 } 166 defer nibReader.Close() 167 168 err = client.PutNIB(n.ID, nibReader) 169 if err != nil { 170 return fmt.Errorf("uploading nib %s failed (%s)", n.ID, err) 171 } 172 173 return nil 174 } 175 176 func (ul *Uploader) uploadObject(objectID string) error { 177 r := ul.r 178 client := ul.client 179 180 Log.Debug(fmt.Sprintf("Uploading object with ID %s", objectID)) 181 object, err := r.GetObjectData(objectID) 182 if err != nil { 183 return fmt.Errorf("unable to load object %s (%s)\n", objectID, err) 184 } 185 defer object.Close() 186 err = client.PutObject(objectID, object) 187 if err != nil { 188 return fmt.Errorf("uploading object %s failed (%s)", objectID, err) 189 } 190 return nil 191 }