github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/rpc/connection.go (about) 1 package rpc 2 3 import ( 4 "sort" 5 "strings" 6 7 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 8 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/cache" 9 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/logger" 10 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/walk" 11 ) 12 13 // Connection carries additional context to rpc calls 14 type Connection struct { 15 Chain string 16 Store *cache.Store // Cache Store to use for read/write. Write can be disabled by setting Store to read-only mode 17 LatestBlockTimestamp base.Timestamp 18 EnabledMap map[walk.CacheType]bool 19 } 20 21 // settings allows every command has its own options type, we have to 22 // accept any here, but will use interfaces to read the needed information 23 type settings struct { 24 Chain string 25 ReadonlyCache bool 26 CacheEnabled bool 27 EnabledMap map[walk.CacheType]bool 28 } 29 30 func NewConnection(chain string, cacheEnabled bool, caches map[walk.CacheType]bool) *Connection { 31 settings := settings{ 32 Chain: chain, 33 CacheEnabled: cacheEnabled, 34 EnabledMap: caches, 35 } 36 return settings.GetRpcConnection() 37 } 38 39 func TempConnection(chain string) *Connection { 40 settings := settings{ 41 Chain: chain, 42 } 43 return settings.GetRpcConnection() 44 } 45 46 func NewReadOnlyConnection(chain string) *Connection { 47 settings := settings{ 48 Chain: chain, 49 ReadonlyCache: true, 50 } 51 return settings.GetRpcConnection() 52 } 53 54 // GetRpcConnection builds the store and enables the caches and returns the RPC connection 55 func (settings settings) GetRpcConnection() *Connection { 56 forceReadonly := !settings.CacheEnabled || settings.ReadonlyCache 57 58 var store *cache.Store 59 var err error 60 if store, err = cache.NewStore(&cache.StoreOptions{ 61 Location: cache.FsCache, 62 Chain: settings.Chain, 63 ReadOnly: forceReadonly, 64 }); err != nil { 65 // If there was an error, we won't use the cache 66 logger.Warn("Cannot initialize cache:", err) 67 } 68 69 ret := &Connection{ 70 Chain: settings.Chain, 71 Store: store, 72 EnabledMap: settings.EnabledMap, 73 } 74 75 if store != nil && !store.ReadOnly() { 76 ret.LatestBlockTimestamp = ret.GetBlockTimestamp(base.NOPOSN) 77 } 78 79 return ret 80 } 81 82 // StoreReadable is a shorthand to check if Store is initialized. It will return 83 // false for nil pointer to Connection 84 func (conn *Connection) StoreReadable() bool { 85 if conn == nil { 86 logger.Fatal("should not happen ==> implementation error in StoreReadable.") 87 } 88 89 return conn.Store != nil 90 } 91 92 func (conn *Connection) StoreWritable() bool { 93 if !conn.StoreReadable() { 94 return false 95 } 96 return !conn.Store.ReadOnly() 97 } 98 99 // TestLog prints the enabledMap to the log. Note this routine gets called prior to full initialization, thus it takes the enabledMap 100 func (conn *Connection) TestLog(caches map[walk.CacheType]bool) { 101 if conn.StoreWritable() { 102 enabled := []string{} 103 for k, v := range caches { 104 if v { 105 enabled = append(enabled, k.String()) 106 } 107 } 108 sort.Strings(enabled) 109 logger.TestLog(len(enabled) > 0, "Enabled: ", strings.Join(enabled, ", ")) 110 } 111 // logger.TestLog(options.LatestBlockTimestamp != 0, "LatestBlockTimestamp: ", options.LatestBlockTimestamp) 112 }