github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/manifest/manifest_save.go (about)

     1  package manifest
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"sort"
     8  
     9  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
    10  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/file"
    11  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
    12  )
    13  
    14  // SaveManifest writes the manifest to a file in JSON format. It first removes any
    15  // duplicate chunks and sorts them. It then marshals the manifest into JSON and
    16  // writes it to the file. The function takes the chain name and file name as arguments.
    17  func (m *Manifest) SaveManifest(chain, fileName string) error {
    18  	m.Config = config.GetScrape(chain)
    19  	m.Config.ChannelCount = 0 // Exclude ChannelCount from the JSON
    20  
    21  	w, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
    22  	if err != nil {
    23  		return fmt.Errorf("creating file: %s", err)
    24  	}
    25  	defer func() {
    26  		w.Close()
    27  		config.SetExpectedVersion(m.Version)
    28  	}()
    29  
    30  	err = file.Lock(w)
    31  	if err != nil {
    32  		return fmt.Errorf("locking file: %s", err)
    33  	}
    34  	defer func() {
    35  		_ = file.Unlock(w)
    36  	}()
    37  
    38  	m.removeDuplicatesAndSort()
    39  
    40  	outputBytes, err := json.MarshalIndent(m, "", "  ")
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	_, err = w.Write(outputBytes)
    46  	return err
    47  }
    48  
    49  // removeDuplicatesAndSort is a helper function that removes duplicate chunks from the manifest
    50  // and sorts the remaining chunks by their range. It uses a map to track seen ranges and a slice
    51  // to store unique chunks. It then sorts the slice and updates the manifest's chunks.
    52  func (m *Manifest) removeDuplicatesAndSort() {
    53  	seen := make(map[string]bool)
    54  	chunks := make([]types.ChunkRecord, 0, len(m.Chunks))
    55  
    56  	for i := len(m.Chunks) - 1; i >= 0; i-- {
    57  		if !seen[m.Chunks[i].Range] {
    58  			seen[m.Chunks[i].Range] = true
    59  			chunks = append(chunks, m.Chunks[i])
    60  		}
    61  	}
    62  
    63  	sort.Slice(chunks, func(i, j int) bool {
    64  		return chunks[i].Range < chunks[j].Range
    65  	})
    66  
    67  	m.Chunks = chunks
    68  }