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  }