fix(splitter): reclaim idle nicehash mappers
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
187a366d74
commit
e594b04d7c
2 changed files with 97 additions and 1 deletions
92
splitter/nicehash/gc_test.go
Normal file
92
splitter/nicehash/gc_test.go
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
package nicehash
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type gcStrategy struct {
|
||||
mu sync.Mutex
|
||||
disconnected bool
|
||||
active bool
|
||||
}
|
||||
|
||||
func (s *gcStrategy) Connect() {}
|
||||
|
||||
func (s *gcStrategy) Submit(jobID, nonce, result, algo string) int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *gcStrategy) Disconnect() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.disconnected = true
|
||||
}
|
||||
|
||||
func (s *gcStrategy) IsActive() bool {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.active
|
||||
}
|
||||
|
||||
func TestNonceSplitter_GC_Good(t *testing.T) {
|
||||
strategy := &gcStrategy{active: false}
|
||||
mapper := &NonceMapper{
|
||||
id: 42,
|
||||
storage: NewNonceStorage(),
|
||||
strategy: strategy,
|
||||
lastUsed: time.Now().Add(-2 * time.Minute),
|
||||
pending: make(map[int64]SubmitContext),
|
||||
}
|
||||
mapper.storage.slots[0] = -1
|
||||
|
||||
splitter := &NonceSplitter{
|
||||
mappers: []*NonceMapper{mapper},
|
||||
byID: map[int64]*NonceMapper{mapper.id: mapper},
|
||||
}
|
||||
|
||||
splitter.GC()
|
||||
|
||||
if len(splitter.mappers) != 0 {
|
||||
t.Fatalf("expected idle mapper to be reclaimed, got %d mapper(s)", len(splitter.mappers))
|
||||
}
|
||||
if _, ok := splitter.byID[mapper.id]; ok {
|
||||
t.Fatalf("expected reclaimed mapper to be removed from lookup table")
|
||||
}
|
||||
if !strategy.disconnected {
|
||||
t.Fatalf("expected reclaimed mapper strategy to be disconnected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonceSplitter_GC_Bad(t *testing.T) {
|
||||
var splitter *NonceSplitter
|
||||
|
||||
splitter.GC()
|
||||
}
|
||||
|
||||
func TestNonceSplitter_GC_Ugly(t *testing.T) {
|
||||
strategy := &gcStrategy{active: true}
|
||||
mapper := &NonceMapper{
|
||||
id: 99,
|
||||
storage: NewNonceStorage(),
|
||||
strategy: strategy,
|
||||
lastUsed: time.Now().Add(-2 * time.Minute),
|
||||
pending: make(map[int64]SubmitContext),
|
||||
}
|
||||
mapper.storage.slots[0] = 7
|
||||
|
||||
splitter := &NonceSplitter{
|
||||
mappers: []*NonceMapper{mapper},
|
||||
byID: map[int64]*NonceMapper{mapper.id: mapper},
|
||||
}
|
||||
|
||||
splitter.GC()
|
||||
|
||||
if len(splitter.mappers) != 1 {
|
||||
t.Fatalf("expected active mapper to remain, got %d mapper(s)", len(splitter.mappers))
|
||||
}
|
||||
if strategy.disconnected {
|
||||
t.Fatalf("expected active mapper to stay connected")
|
||||
}
|
||||
}
|
||||
|
|
@ -98,13 +98,17 @@ func (s *NonceSplitter) GC() {
|
|||
now := time.Now()
|
||||
next := s.mappers[:0]
|
||||
for _, mapper := range s.mappers {
|
||||
if mapper == nil || mapper.storage == nil {
|
||||
continue
|
||||
}
|
||||
free, dead, active := mapper.storage.SlotCount()
|
||||
if active == 0 && dead == 0 && now.Sub(mapper.lastUsed) > time.Minute {
|
||||
if active == 0 && now.Sub(mapper.lastUsed) > time.Minute {
|
||||
if mapper.strategy != nil {
|
||||
mapper.strategy.Disconnect()
|
||||
}
|
||||
delete(s.byID, mapper.id)
|
||||
_ = free
|
||||
_ = dead
|
||||
continue
|
||||
}
|
||||
next = append(next, mapper)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue