Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prio nodes farmerbot #988

Merged
merged 11 commits into from
May 19, 2024
2 changes: 2 additions & 0 deletions farmerbot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ included_nodes: [optional, if no nodes are added then the farmerbot will include
- "<your node ID to be included, required at least 2>"
excluded_nodes:
- "<your node ID to be excluded, optional>"
priority:
rawdaGastan marked this conversation as resolved.
Show resolved Hide resolved
- "<your node ID to have a priority in nodes management, optional>"
never_shutdown_nodes:
- "<your node ID to be never shutdown, optional>"
power:
Expand Down
27 changes: 27 additions & 0 deletions farmerbot/internal/farmerbot.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ func (f *FarmerBot) iterateOnNodes(ctx context.Context, subConn Substrate) error
}
}

farmNodes = addPriorityToNodes(f.state.config.PriorityNodes, farmNodes)

for _, nodeID := range farmNodes {
if slices.Contains(f.state.config.ExcludedNodes, nodeID) {
continue
Expand Down Expand Up @@ -328,6 +330,31 @@ func (f *FarmerBot) iterateOnNodes(ctx context.Context, subConn Substrate) error
return nil
}

func addPriorityToNodes(priorityNodes, farmNodes []uint32) []uint32 {
updatedPriorityNodes := make([]uint32, len(priorityNodes))
copy(updatedPriorityNodes, priorityNodes)

// remove nodes that don't exist in farm from priority nodes
for i := 0; i < len(updatedPriorityNodes); i++ {
nodeID := updatedPriorityNodes[i]
if !slices.Contains(farmNodes, nodeID) {
updatedPriorityNodes = slices.Delete(updatedPriorityNodes, i, i+1)
i--
}
}

// remove priority nodes from farm nodes
for i := 0; i < len(farmNodes); i++ {
if slices.Contains(updatedPriorityNodes, farmNodes[i]) {
farmNodes = slices.Delete(farmNodes, i, i+1)
i--
}
}

// append priority and the rest of farm nodes
return append(updatedPriorityNodes, farmNodes...)
}

func (f *FarmerBot) addOrUpdateNode(ctx context.Context, subConn Substrate, nodeID uint32) error {
neverShutDown := slices.Contains(f.state.config.NeverShutDownNodes, nodeID)

Expand Down
5 changes: 3 additions & 2 deletions farmerbot/internal/farmerbot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func TestFarmerbot(t *testing.T) {
inputs := Config{
FarmID: 1,
IncludedNodes: []uint32{1, 2},
PriorityNodes: []uint32{2},
xmonader marked this conversation as resolved.
Show resolved Hide resolved
Power: power{WakeUpThreshold: 50},
}

Expand Down Expand Up @@ -66,10 +67,10 @@ func TestFarmerbot(t *testing.T) {
assert.True(t, errors.Is(err, substrate.ErrNotFound))
})

t.Run("test iterateOnNodes: update nodes and power off extra node (periodic wake up: already on)", func(t *testing.T) {
t.Run("test iterateOnNodes: update nodes and power off extra node (respect priority - periodic wake up: already on)", func(t *testing.T) {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, true, resources, []string{}, false, false)

sub.EXPECT().SetNodePowerTarget(farmerbot.identity, gomock.Any(), false).Return(types.Hash{}, nil)
sub.EXPECT().SetNodePowerTarget(farmerbot.identity, uint32(2), false).Return(types.Hash{}, nil)

err = farmerbot.iterateOnNodes(ctx, sub)
assert.NoError(t, err)
Expand Down
20 changes: 18 additions & 2 deletions farmerbot/internal/power.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,15 @@ func calculateResourceUsage(nodes map[uint32]node) (uint64, uint64) {
}

func (f *FarmerBot) resourceUsageTooHigh(sub Substrate) error {
for nodeID, node := range f.nodes {
nodesKeys := make([]uint32, 0, len(f.nodes))
for k := range f.nodes {
nodesKeys = append(nodesKeys, k)
}

for i := 0; i < len(f.nodes); i++ {
nodeID := nodesKeys[i]
node := f.nodes[nodeID]

rawdaGastan marked this conversation as resolved.
Show resolved Hide resolved
if node.powerState == off {
return f.powerOn(sub, nodeID)
}
Expand Down Expand Up @@ -180,8 +188,16 @@ func (f *FarmerBot) resourceUsageTooLow(sub Substrate, usedResources, totalResou
newTotalResources := totalResources
nodesLeftOnline := len(onNodes)

// use keys to keep nodes order
nodesAllowedToShutdownKeys := make([]uint32, 0, len(nodesAllowedToShutdown))
for k := range nodesAllowedToShutdown {
nodesAllowedToShutdownKeys = append(nodesAllowedToShutdownKeys, k)
}

// shutdown a node if there is more than an unused node (aka keep at least one node online)
for _, node := range nodesAllowedToShutdown {
for i := 0; i < len(nodesAllowedToShutdown); i++ {
node := nodesAllowedToShutdown[nodesAllowedToShutdownKeys[i]]

if nodesLeftOnline == 1 {
break
}
Expand Down
2 changes: 2 additions & 0 deletions farmerbot/internal/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ func fetchNodes(ctx context.Context, sub Substrate, rmbNodeClient RMB, config Co
return nil, err
}

farmNodes = addPriorityToNodes(config.PriorityNodes, farmNodes)

for _, nodeID := range farmNodes {
if slices.Contains(config.ExcludedNodes, nodeID) {
continue
Expand Down
1 change: 1 addition & 0 deletions farmerbot/internal/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Config struct {
FarmID uint32 `yaml:"farm_id"`
IncludedNodes []uint32 `yaml:"included_nodes"`
ExcludedNodes []uint32 `yaml:"excluded_nodes"`
PriorityNodes []uint32 `yaml:"priority_nodes"`
NeverShutDownNodes []uint32 `yaml:"never_shutdown_nodes"`
Power power `yaml:"power"`
ContinueOnPoweringOnErr bool
Expand Down
Loading