github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/transferfiles/state/transfersnapshot.go (about)

     1  package state
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/jfrog/jfrog-cli-core/v2/utils/reposnapshot"
     8  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
     9  )
    10  
    11  var saveRepoSnapshotMutex sync.Mutex
    12  
    13  type SnapshotActionFunc func(rts *RepoTransferSnapshot) error
    14  
    15  var snapshotSaveIntervalMin = snapshotSaveIntervalMinDefault
    16  
    17  const snapshotSaveIntervalMinDefault = 10
    18  
    19  // RepoTransferSnapshot handles saving and loading the repository's transfer snapshot.
    20  // A repository transfer snapshot stores the progress of transferring a repository, as explained in RepoSnapshotManager.
    21  // In case a transfer is interrupted, the transfer can continue from it's saved snapshot instead of starting from scratch.
    22  type RepoTransferSnapshot struct {
    23  	snapshotManager   reposnapshot.RepoSnapshotManager
    24  	lastSaveTimestamp time.Time
    25  	// This boolean marks that this snapshot continues a previous run. It allows skipping certain checks if it was not loaded, because some data is known to be new.
    26  	loadedFromSnapshot bool
    27  }
    28  
    29  // Runs the provided action on the snapshot manager, and periodically saves the repo state and snapshot to the snapshot dir.
    30  func (ts *TransferStateManager) snapshotAction(action SnapshotActionFunc) (err error) {
    31  	if ts.repoTransferSnapshot == nil {
    32  		return errorutils.CheckErrorf("invalid call to snapshot manager before it was initialized")
    33  	}
    34  	if err = action(ts.repoTransferSnapshot); err != nil {
    35  		return err
    36  	}
    37  
    38  	now := time.Now()
    39  	if now.Sub(ts.repoTransferSnapshot.lastSaveTimestamp).Minutes() < float64(snapshotSaveIntervalMin) {
    40  		return nil
    41  	}
    42  
    43  	if !saveRepoSnapshotMutex.TryLock() {
    44  		return nil
    45  	}
    46  	defer saveRepoSnapshotMutex.Unlock()
    47  
    48  	ts.repoTransferSnapshot.lastSaveTimestamp = now
    49  	if err = ts.repoTransferSnapshot.snapshotManager.PersistRepoSnapshot(); err != nil {
    50  		return err
    51  	}
    52  
    53  	return ts.persistTransferState(true)
    54  }
    55  
    56  func (ts *TransferStateManager) LookUpNode(relativePath string) (requestedNode *reposnapshot.Node, err error) {
    57  	err = ts.snapshotAction(func(rts *RepoTransferSnapshot) error {
    58  		requestedNode, err = rts.snapshotManager.LookUpNode(relativePath)
    59  		return err
    60  	})
    61  	return
    62  }
    63  
    64  func (ts *TransferStateManager) WasSnapshotLoaded() bool {
    65  	return ts.repoTransferSnapshot.loadedFromSnapshot
    66  }
    67  
    68  func (ts *TransferStateManager) GetDirectorySnapshotNodeWithLru(relativePath string) (node *reposnapshot.Node, err error) {
    69  	err = ts.snapshotAction(func(rts *RepoTransferSnapshot) error {
    70  		node, err = rts.snapshotManager.GetDirectorySnapshotNodeWithLru(relativePath)
    71  		return err
    72  	})
    73  	return
    74  }
    75  
    76  func (ts *TransferStateManager) DisableRepoTransferSnapshot() {
    77  	ts.repoTransferSnapshot = nil
    78  }
    79  
    80  func (ts *TransferStateManager) IsRepoTransferSnapshotEnabled() bool {
    81  	return ts.repoTransferSnapshot != nil
    82  }
    83  
    84  func loadRepoTransferSnapshot(repoKey, snapshotFilePath string) (*RepoTransferSnapshot, bool, error) {
    85  	snapshotManager, exists, err := reposnapshot.LoadRepoSnapshotManager(repoKey, snapshotFilePath)
    86  	if err != nil || !exists {
    87  		return nil, exists, err
    88  	}
    89  	return &RepoTransferSnapshot{snapshotManager: snapshotManager, lastSaveTimestamp: time.Now(), loadedFromSnapshot: true}, true, nil
    90  }
    91  
    92  func createRepoTransferSnapshot(repoKey, snapshotFilePath string) *RepoTransferSnapshot {
    93  	return &RepoTransferSnapshot{snapshotManager: reposnapshot.CreateRepoSnapshotManager(repoKey, snapshotFilePath), lastSaveTimestamp: time.Now()}
    94  }