github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/scrape/scrape_manager_utils.go (about)

     1  package scrapePkg
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
     9  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/colors"
    10  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
    11  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/logger"
    12  )
    13  
    14  // Report prints out a report of the progress of the scraper.
    15  func (bm *BlazeManager) report(nBlocks, perChunk, nChunks, nAppsNow, nAppsFound, nAddrsFound int) {
    16  	_ = nBlocks // linter
    17  	nNeeded := perChunk - base.Min(perChunk, nAppsNow)
    18  	appsPerAddr := float64(nAppsFound) / float64(nAddrsFound)
    19  	pctFull := float64(nAppsNow) / float64(perChunk)
    20  	pctStr := fmt.Sprintf("%0.1f%%", pctFull*100)
    21  	if len(pctStr) < 5 {
    22  		pctStr = " " + pctStr
    23  	}
    24  	chunksStr := ""
    25  	if nChunks > 0 {
    26  		chunksStr = fmt.Sprintf(" created {%d} chunk(s)", nChunks)
    27  	} else {
    28  		chunksStr = fmt.Sprintf(" %s", bm.chain)
    29  	}
    30  
    31  	report := `%7.7s @#% 9d}: {% 8d}/{% 8d} ({%0.1f apps/addr}) stage {% 8d} need {% 8d} (@%5.5s})%s`
    32  	msg := fmt.Sprintf(report,
    33  		bm.chain,
    34  		bm.EndBlock()-1,
    35  		nAppsFound,
    36  		nAddrsFound,
    37  		appsPerAddr,
    38  		nAppsNow,
    39  		nNeeded,
    40  		pctStr,
    41  		chunksStr,
    42  	)
    43  	logger.Info(colors.Colored(msg))
    44  }
    45  
    46  // Pause goes to sleep for a period of time based on the settings.
    47  func (opts *ScrapeOptions) pause(ctx context.Context, dist base.Blknum) {
    48  	// sleepOrCancel is a helper that waits ms milliseconds unless the context has been cancelled.
    49  	sleepOrCancel := func(ms time.Duration) (ok bool) {
    50  		// We need to create a new timer explicitly, so we can cleanup the memory.
    51  		// See the documentation of time.After
    52  		timer := time.NewTimer(ms)
    53  		select {
    54  		case <-ctx.Done():
    55  			// If the context has been cancelled, we need to drain the timer's channel
    56  			// to make sure nothing "leaks"
    57  			if !timer.Stop() {
    58  				<-timer.C
    59  			}
    60  			return false
    61  		case <-timer.C:
    62  			// Since we have just read the channel's value, we can just call Stop
    63  			timer.Stop()
    64  			return true
    65  		}
    66  	}
    67  	// we always pause at least a quarter of a second to allow the node to 'rest'
    68  	if !sleepOrCancel(250 * time.Millisecond) {
    69  		return
    70  	}
    71  	isDefaultSleep := opts.Sleep >= 13 && opts.Sleep <= 14
    72  	shouldSleep := !isDefaultSleep || dist <= base.Blknum(2*config.GetScrape(opts.Globals.Chain).UnripeDist)
    73  	if shouldSleep {
    74  		sleep := opts.Sleep // this value may change elsewhere allow us to break out of sleeping????
    75  		logger.Progress(sleep > 1, "Sleeping for", sleep, "seconds -", dist, "away from head.")
    76  		halfSecs := (sleep * 2) - 1 // we already slept one quarter of a second
    77  		for i := 0; i < int(halfSecs); i++ {
    78  			if !sleepOrCancel(500 * time.Millisecond) {
    79  				return
    80  			}
    81  		}
    82  	}
    83  }