go-proxy/splitter/simple/mapper.go
Virgil 7d2d309529 feat(proxy): close RFC gaps
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-04 10:52:30 +00:00

108 lines
2.3 KiB
Go

package simple
import (
"sync"
"time"
"dappco.re/go/core/proxy"
"dappco.re/go/core/proxy/pool"
)
// SimpleMapper holds one outbound pool connection and serves at most one active miner
// at a time. It becomes idle when the miner disconnects and may be reclaimed for the
// next login.
//
// m := simple.NewSimpleMapper(id, strategy)
type SimpleMapper struct {
id int64
miner *proxy.Miner // nil when idle
strategy pool.Strategy
events *proxy.EventBus
pending map[int64]simpleSubmitContext
job proxy.Job
prevJob proxy.Job
idleAt time.Time // zero when active
stopped bool
mu sync.Mutex
}
type simpleSubmitContext struct {
RequestID int64
Expired bool
}
// NewSimpleMapper stores the mapper ID and strategy.
//
// mapper := simple.NewSimpleMapper(1, strategy)
func NewSimpleMapper(id int64, strategy pool.Strategy) *SimpleMapper {
return &SimpleMapper{id: id, strategy: strategy, pending: make(map[int64]simpleSubmitContext)}
}
func (m *SimpleMapper) OnJob(job proxy.Job) {
if !job.IsValid() {
return
}
m.mu.Lock()
if m.job.ClientID == job.ClientID || m.job.ClientID == "" {
m.prevJob = m.job
} else {
m.prevJob = proxy.Job{}
}
m.job = job
miner := m.miner
m.mu.Unlock()
if miner != nil {
miner.ForwardJob(job, job.Algo)
}
}
func (m *SimpleMapper) JobStatus(id string) (valid bool, expired bool) {
m.mu.Lock()
defer m.mu.Unlock()
if id == "" {
return false, false
}
if id == m.job.JobID {
return true, false
}
if id == m.prevJob.JobID {
return true, true
}
return false, false
}
func (m *SimpleMapper) OnResultAccepted(sequence int64, accepted bool, errorMessage string) {
m.mu.Lock()
context, exists := m.pending[sequence]
miner := m.miner
if !exists {
m.mu.Unlock()
return
}
delete(m.pending, sequence)
m.mu.Unlock()
if miner == nil {
return
}
if accepted {
if m.events != nil {
m.events.Dispatch(proxy.Event{Type: proxy.EventAccept, Miner: miner, Diff: miner.Diff(), Expired: context.Expired})
}
miner.Success(context.RequestID, "OK")
return
}
if m.events != nil {
m.events.Dispatch(proxy.Event{Type: proxy.EventReject, Miner: miner, Diff: miner.Diff(), Error: errorMessage, Expired: context.Expired})
}
miner.ReplyWithError(context.RequestID, errorMessage)
}
func (m *SimpleMapper) OnDisconnect() {
m.stopped = true
}