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  }