/
handle_show.go
100 lines (85 loc) · 2.78 KB
/
handle_show.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright 2021 The TrueBlocks Authors. All rights reserved.
// Use of this source code is governed by a license that can
// be found in the LICENSE file.
package blocksPkg
import (
"context"
"fmt"
"sort"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/identifiers"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/logger"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/output"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/utils"
)
func (opts *BlocksOptions) HandleShow() error {
chain := opts.Globals.Chain
testMode := opts.Globals.TestMode
nErrors := 0
ctx, cancel := context.WithCancel(context.Background())
fetchData := func(modelChan chan types.Modeler[types.RawBlock], errorChan chan error) {
apps, _, err := identifiers.IdsToApps(chain, opts.BlockIds)
if err != nil {
errorChan <- err
cancel()
}
if sliceOfMaps, cnt, err := types.AsSliceOfMaps[types.SimpleBlock[types.SimpleTransaction]](apps, false); err != nil {
errorChan <- err
cancel()
} else if cnt == 0 {
errorChan <- fmt.Errorf("no blocks found for the query")
cancel()
} else {
bar := logger.NewBar(logger.BarOptions{
Enabled: !testMode && !utils.IsTerminal(),
Total: int64(cnt),
})
for _, thisMap := range sliceOfMaps {
for app := range thisMap {
thisMap[app] = new(types.SimpleBlock[types.SimpleTransaction])
}
items := make([]*types.SimpleBlock[types.SimpleTransaction], 0, len(thisMap))
iterFunc := func(app types.SimpleAppearance, value *types.SimpleBlock[types.SimpleTransaction]) error {
bn := uint64(app.BlockNumber)
if block, err := opts.Conn.GetBlockBodyByNumber(bn); err != nil {
delete(thisMap, app)
return err
} else {
*value = block
bar.Tick()
}
return nil
}
iterErrorChan := make(chan error)
iterCtx, iterCancel := context.WithCancel(context.Background())
defer iterCancel()
go utils.IterateOverMap(iterCtx, iterErrorChan, thisMap, iterFunc)
for err := range iterErrorChan {
if !testMode || nErrors == 0 {
errorChan <- err
nErrors++
}
}
for _, item := range thisMap {
items = append(items, item)
}
sort.Slice(items, func(i, j int) bool {
if items[i].BlockNumber == items[j].BlockNumber {
return items[i].Hash.Hex() < items[j].Hash.Hex()
}
return items[i].BlockNumber < items[j].BlockNumber
})
for _, item := range items {
modelChan <- item
}
}
bar.Finish(true /* newLine */)
}
}
extra := map[string]interface{}{
"hashes": opts.Hashes,
"uncles": opts.Uncles,
"articulate": opts.Articulate,
}
return output.StreamMany(ctx, fetchData, opts.Globals.OutputOptsWithExtra(extra))
}