Skip to content

Commit

Permalink
fix: incorrect state error for shorter epoch length (#1192)
Browse files Browse the repository at this point in the history
* refactor: moved resetting cache in a separate go routine

* fix: fixed default and max/min values for wait and buffer from config

* refactor: separated out resetting job/collection cache in a function

* refactor: recorrected 0 value for buffer log

* fix: cannot reset cache in commit state

* refactor: defined buffer state sleep time in constants

* refactor: added method called for ResetAssetCache and added tests

* refactor: introduced resetting asset cache in a separate goroutine at the very start

* refactor: removed unused errChan

* refactor: Moved ticker to HandleResetCache()
  • Loading branch information
Yashk767 authored Mar 1, 2024
1 parent 8aac72a commit 2fd96c8
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 35 deletions.
14 changes: 7 additions & 7 deletions cmd/config-utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ func (*UtilsStruct) GetMultiplier() (float32, error) {
//This function returns the buffer percent
func (*UtilsStruct) GetBufferPercent() (int32, error) {
const (
MinBufferPercent = 10
MaxBufferPercent = 30
MinBufferPercent = 0
MaxBufferPercent = 5
)

bufferPercent, err := getConfigValue("buffer", "int32", core.DefaultBufferPercent, "buffer")
Expand All @@ -228,7 +228,7 @@ func (*UtilsStruct) GetBufferPercent() (int32, error) {

// If bufferPercent is 0, use the default value.
if bufferPercentInt32 == 0 {
log.Debugf("BufferPercent is unset, using default value %d", core.DefaultBufferPercent)
log.Debugf("BufferPercent is unset or set to 0, using its default %d value", core.DefaultBufferPercent)
return core.DefaultBufferPercent, nil
}

Expand All @@ -238,8 +238,8 @@ func (*UtilsStruct) GetBufferPercent() (int32, error) {
//This function returns the wait time
func (*UtilsStruct) GetWaitTime() (int32, error) {
const (
MinWaitTime = 1 // Minimum wait time in seconds
MaxWaitTime = 30 // Maximum wait time in seconds
MinWaitTime = 1 // Minimum wait time in seconds
MaxWaitTime = 5 // Maximum wait time in seconds
)

waitTime, err := getConfigValue("wait", "int32", core.DefaultWaitTime, "wait")
Expand Down Expand Up @@ -335,7 +335,7 @@ func (*UtilsStruct) GetGasLimitOverride() (uint64, error) {
func (*UtilsStruct) GetRPCTimeout() (int64, error) {
const (
MinRPCTimeout = 10 // Minimum RPC timeout in seconds
MaxRPCTimeout = 60 // Maximum RPC timeout in seconds
MaxRPCTimeout = 20 // Maximum RPC timeout in seconds
)

rpcTimeout, err := getConfigValue("rpcTimeout", "int64", core.DefaultRPCTimeout, "rpcTimeout")
Expand All @@ -357,7 +357,7 @@ func (*UtilsStruct) GetRPCTimeout() (int64, error) {
func (*UtilsStruct) GetHTTPTimeout() (int64, error) {
const (
MinHTTPTimeout = 10 // Minimum HTTP timeout in seconds
MaxHTTPTimeout = 60 // Maximum HTTP timeout in seconds
MaxHTTPTimeout = 20 // Maximum HTTP timeout in seconds
)

httpTimeout, err := getConfigValue("httpTimeout", "int64", core.DefaultHTTPTimeout, "httpTimeout")
Expand Down
16 changes: 8 additions & 8 deletions cmd/config-utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,9 @@ func TestGetBufferPercent(t *testing.T) {
name: "Test 1: When buffer percent is fetched from root flag",
args: args{
isFlagSet: true,
bufferPercent: 15,
bufferPercent: 5,
},
want: 15,
want: 5,
wantErr: nil,
},
{
Expand All @@ -278,9 +278,9 @@ func TestGetBufferPercent(t *testing.T) {
name: "Test 3: When buffer value is fetched from config",
useDummyConfigFile: true,
args: args{
bufferInTestConfig: 30,
bufferInTestConfig: 1,
},
want: 30,
want: 1,
wantErr: nil,
},
{
Expand Down Expand Up @@ -1130,9 +1130,9 @@ func TestGetWaitTime(t *testing.T) {
name: "Test 1: When wait time is fetched from root flag",
args: args{
isFlagSet: true,
waitTime: 10,
waitTime: 2,
},
want: 10,
want: 2,
wantErr: nil,
},
{
Expand All @@ -1148,9 +1148,9 @@ func TestGetWaitTime(t *testing.T) {
name: "Test 3: When wait time value is fetched from config",
useDummyConfigFile: true,
args: args{
waitInTestConfig: 20,
waitInTestConfig: 3,
},
want: 20,
want: 3,
wantErr: nil,
},
{
Expand Down
20 changes: 5 additions & 15 deletions cmd/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ func (*UtilsStruct) ExecuteVote(flagSet *pflag.FlagSet) {
err = cmdUtils.InitAssetCache(client)
utils.CheckError("Error in initializing asset cache: ", err)

go utils.HandleResetCache(client, config.BufferPercent)

log.Debugf("Calling Vote() with arguments rogueData = %+v, account address = %s, backup node actions to ignore = %s", rogueData, account.Address, backupNodeActionsToIgnore)
if err := cmdUtils.Vote(context.Background(), config, client, rogueData, account, backupNodeActionsToIgnore); err != nil {
log.Errorf("%v\n", err)
Expand Down Expand Up @@ -126,22 +128,10 @@ func (*UtilsStruct) HandleExit() {

//This function handles all the states of voting
func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error {
assetCacheTicker := time.NewTicker(time.Second * time.Duration(core.AssetCacheExpiry))
header, err := clientUtils.GetLatestBlockWithRetry(client)
utils.CheckError("Error in getting block: ", err)
for {
select {
case <-assetCacheTicker.C:
log.Info("ASSET CACHE EXPIRED!")
log.Info("INITIALIZING JOBS AND COLLECTIONS CACHE AGAIN...")
if err := utils.InitJobsCache(client); err != nil {
log.Error("Error in initializing jobs cache: ", err)
continue
}
if err := utils.InitCollectionsCache(client); err != nil {
log.Error("Error in initializing collections cache: ", err)
continue
}
case <-ctx.Done():
return nil
default:
Expand Down Expand Up @@ -319,8 +309,8 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account,
}
}
case -1:
if config.WaitTime > 5 {
timeUtils.Sleep(5 * time.Second)
if config.WaitTime >= core.BufferStateSleepTime {
timeUtils.Sleep(time.Second * time.Duration(core.BufferStateSleepTime))
return
}
}
Expand Down Expand Up @@ -529,7 +519,7 @@ func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Config
if revealTxn != core.NilHash {
waitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, revealTxn.Hex())
if waitForBlockCompletionErr != nil {
log.Error("Error in WaitForBlockCompletionErr for reveal: ", err)
log.Error("Error in WaitForBlockCompletionErr for reveal: ", waitForBlockCompletionErr)
return err
}
}
Expand Down
8 changes: 4 additions & 4 deletions config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ then
GAS_MULTIPLIER=1.0
fi

read -rp "Buffer Percent: (20) " BUFFER
read -rp "Buffer Percent: (0) " BUFFER
if [ -z "$BUFFER" ];
then
BUFFER=20
BUFFER=0
fi

read -rp "Wait Time: (1) " WAIT_TIME
if [ -z "$WAIT_TIME" ]; then
WAIT_TIME=1
fi

read -rp "Gas Price: (1) " GAS_PRICE
read -rp "Gas Price: (0) " GAS_PRICE
if [ -z "$GAS_PRICE" ]; then
GAS_PRICE=1
GAS_PRICE=0
fi

read -rp "Gas Limit Increment : (2) " GAS_LIMIT
Expand Down
5 changes: 4 additions & 1 deletion core/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var BlockCompletionTimeout = 30
//Following are the default config values for all the config parameters

var DefaultGasMultiplier float32 = 1.0
var DefaultBufferPercent int32 = 20
var DefaultBufferPercent int32 = 0
var DefaultGasPrice int32 = 0
var DefaultWaitTime int32 = 1
var DefaultGasLimit float32 = 2
Expand All @@ -30,6 +30,9 @@ var DefaultRPCTimeout int64 = 10
var DefaultHTTPTimeout int64 = 10
var DefaultLogLevel = ""

//BufferStateSleepTime is the sleeping time whenever buffer state hits
var BufferStateSleepTime int32 = 2

//Following are the default logFile parameters in config

var DefaultLogFileMaxSize = 200
Expand Down
43 changes: 43 additions & 0 deletions utils/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,49 @@ func (*UtilsStruct) HandleOfficialJobsFromJSONFile(client *ethclient.Client, col
return overrideJobs, overriddenJobIds
}

func HandleResetCache(client *ethclient.Client, bufferPercent int32) {
assetCacheTicker := time.NewTicker(time.Second * time.Duration(core.AssetCacheExpiry))
defer assetCacheTicker.Stop()

for {
<-assetCacheTicker.C // Wait for the next tick
log.Info("ASSET CACHE EXPIRED! INITIALIZING JOBS AND COLLECTIONS CACHE AGAIN...")
if err := UtilsInterface.ResetAssetCache(client, bufferPercent); err != nil {
log.Errorf("Error resetting asset cache: %v", err)
}
}
}

func (*UtilsStruct) ResetAssetCache(client *ethclient.Client, bufferPercent int32) error {
state, err := UtilsInterface.GetBufferedState(client, bufferPercent)
if err != nil {
log.Error("Error in getting buffered state: ", err)
return err
}
// Avoiding resetting jobs/collections cache in commit state
if state == 0 {
log.Info("ResetAssetCache: Cannot reset Jobs/Collections cache in commit state!")
stateRemainingTime, err := UtilsInterface.GetRemainingTimeOfCurrentState(client, bufferPercent)
if err != nil {
log.Error("Error in getting remaining time of current state: ", err)
return err
}
log.Infof("ResetAssetCache: Waiting for commit state to complete, sleeping for %v seconds...", stateRemainingTime)
time.Sleep(time.Second * time.Duration(stateRemainingTime))
log.Infof("ResetAssetCache: INITIALIZING JOBS AND COLLECTIONS CACHE NOW!")
}

if err := InitJobsCache(client); err != nil {
log.Error("Error in initializing jobs cache: ", err)
return err
}
if err := InitCollectionsCache(client); err != nil {
log.Error("Error in initializing collections cache: ", err)
return err
}
return nil
}

func InitJobsCache(client *ethclient.Client) error {
cache.JobsCache.Mu.Lock()
defer cache.JobsCache.Mu.Unlock()
Expand Down
127 changes: 127 additions & 0 deletions utils/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1638,3 +1638,130 @@ func TestIsJSONCompatible(t *testing.T) {
})
}
}

func TestUtilsStruct_ResetAssetCache(t *testing.T) {
var (
client *ethclient.Client
bufferPercent int32
)

type args struct {
state int64
stateErr error
stateRemainingTime int64
stateRemainingTimeErr error
numOfJobs uint16
numOfJobsErr error
job bindings.StructsJob
jobErr error
numOfCollections uint16
numOfCollectionsErr error
collection bindings.StructsCollection
collectionErr error
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "Successful Reset",
args: args{
state: 1, // Not in commit state
numOfJobs: 2,
job: bindings.StructsJob{Id: 1},
numOfCollections: 2,
collection: bindings.StructsCollection{Id: 1},
},
wantErr: false,
},
{
name: "Successful Reset after waiting in commit state",
args: args{
state: 0, // Not in commit state
stateRemainingTime: 1,
numOfJobs: 1,
job: bindings.StructsJob{Id: 1},
numOfCollections: 1,
collection: bindings.StructsCollection{Id: 1},
},
wantErr: false,
},
{
name: "Error in getting buffered state",
args: args{
stateErr: errors.New("state error"),
},
wantErr: true,
},
{
name: "Error in getting state remaining time when resetting in commit state",
args: args{
state: 0, // In commit state
stateRemainingTimeErr: errors.New("stateRemainingTime error"),
},
wantErr: true,
},
{
name: "Error in getting num Of jobs",
args: args{
state: 1,
numOfJobsErr: errors.New("numOfJobs error"),
},
wantErr: true,
},
{
name: "Error in getting job",
args: args{
state: 1,
numOfJobs: 1,
jobErr: errors.New("job error"),
},
wantErr: true,
},
{
name: "Error in getting num of collections",
args: args{
state: 1,
numOfJobs: 2,
job: bindings.StructsJob{Id: 1},
numOfCollectionsErr: errors.New("numOfCollections error"),
},
wantErr: true,
},
{
name: "Error in getting collection",
args: args{
state: 1,
numOfJobs: 2,
job: bindings.StructsJob{Id: 1},
numOfCollections: 1,
collectionErr: errors.New("collection error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
utilsMock := new(mocks.Utils)
assetManagerMock := new(mocks.AssetManagerUtils)

optionsPackageStruct := OptionsPackageStruct{
UtilsInterface: utilsMock,
AssetManagerInterface: assetManagerMock,
}
utils := StartRazor(optionsPackageStruct)

utilsMock.On("GetBufferedState", mock.Anything, mock.Anything).Return(tt.args.state, tt.args.stateErr)
utilsMock.On("GetRemainingTimeOfCurrentState", mock.Anything, mock.Anything).Return(tt.args.stateRemainingTime, tt.args.stateRemainingTimeErr)
assetManagerMock.On("GetNumJobs", mock.Anything).Return(tt.args.numOfJobs, tt.args.numOfJobsErr)
utilsMock.On("GetNumCollections", mock.Anything).Return(tt.args.numOfCollections, tt.args.numOfCollectionsErr)
utilsMock.On("GetActiveJob", mock.Anything, mock.Anything).Return(tt.args.job, tt.args.jobErr)
assetManagerMock.On("GetCollection", mock.Anything, mock.Anything).Return(tt.args.collection, tt.args.collectionErr)

if err := utils.ResetAssetCache(client, bufferPercent); (err != nil) != tt.wantErr {
t.Errorf("ResetAssetCache() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
1 change: 1 addition & 0 deletions utils/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ type Utils interface {
GetStakedTokenManagerWithOpts(client *ethclient.Client, tokenAddress common.Address) (*bindings.StakedToken, bind.CallOpts)
GetStakerSRZRBalance(client *ethclient.Client, staker bindings.StructsStaker) (*big.Int, error)
CheckPassword(address string, password string) error
ResetAssetCache(client *ethclient.Client, bufferPercent int32) error
}

type EthClientUtils interface {
Expand Down
Loading

0 comments on commit 2fd96c8

Please sign in to comment.