github.com/drone/drone-cache-lib@v0.0.0-20200806063744-981868645a25/cache/cache.go (about)

     1  package cache
     2  
     3  import (
     4  	"io"
     5  
     6  	log "github.com/sirupsen/logrus"
     7  	"github.com/drone/drone-cache-lib/archive"
     8  	"github.com/drone/drone-cache-lib/archive/tar"
     9  	"github.com/drone/drone-cache-lib/storage"
    10  )
    11  
    12  // Cache defines a basic cache object.
    13  type Cache struct {
    14  	s storage.Storage
    15  	a archive.Archive
    16  }
    17  
    18  // New creates a new cache object.
    19  func New(s storage.Storage, a archive.Archive) Cache {
    20  	return Cache{s: s, a: a}
    21  }
    22  
    23  // NewDefault creates a new cache object with tar format.
    24  func NewDefault(s storage.Storage) Cache {
    25  	// Return default Cache that uses tar and flushes items after 7 days
    26  	return New(s, tar.New())
    27  }
    28  
    29  // Rebuild rebuilds the new cache.
    30  func (c Cache) Rebuild(srcs []string, dst string) error {
    31  	return rebuildCache(srcs, dst, c.s, c.a)
    32  }
    33  
    34  // Restore restores the existing cache.
    35  func (c Cache) Restore(src string, fallback string) error {
    36  	err := restoreCache(src, c.s, c.a)
    37  
    38  	if err != nil && fallback != "" && fallback != src {
    39  		log.Warnf("Failed to retrieve %s, trying %s", src, fallback)
    40  		err = restoreCache(fallback, c.s, c.a)
    41  	}
    42  
    43  	// Cache plugin should print an error but it should not return it
    44  	// this is so the build continues even if the cache cant be restored
    45  	if err != nil {
    46  		log.Warnf("Cache could not be restored %s", err)
    47  	}
    48  
    49  	return nil
    50  }
    51  
    52  func restoreCache(src string, s storage.Storage, a archive.Archive) error {
    53  	reader, writer := io.Pipe()
    54  
    55  	cw := make(chan error, 1)
    56  	defer close(cw)
    57  
    58  	go func() {
    59  		defer writer.Close()
    60  
    61  		cw <- s.Get(src, writer)
    62  	}()
    63  
    64  	err := a.Unpack("", reader)
    65  	werr := <-cw
    66  
    67  	if werr != nil {
    68  		return werr
    69  	}
    70  
    71  	return err
    72  }
    73  
    74  func rebuildCache(srcs []string, dst string, s storage.Storage, a archive.Archive) error {
    75  	log.Infof("Rebuilding cache at %s to %s", srcs, dst)
    76  
    77  	reader, writer := io.Pipe()
    78  	defer reader.Close()
    79  
    80  	cw := make(chan error, 1)
    81  	defer close(cw)
    82  
    83  	go func() {
    84  		defer writer.Close()
    85  
    86  		cw <- a.Pack(srcs, writer)
    87  	}()
    88  
    89  	err := s.Put(dst, reader)
    90  	werr := <-cw
    91  
    92  	if werr != nil {
    93  		return werr
    94  	}
    95  
    96  	return err
    97  }