mirror of
https://github.com/luxfi/bft.git
synced 2026-10-30 17:01:54 +00:00
Reapplies the fork's whole delta on top of the merge, as one reviewable diff rather than 43 conflict resolutions. Nothing here changes consensus behaviour. - module github.com/luxfi/bft, Go 1.26.4; root package simplex -> bft, which would otherwise collide with the simplex/ subpackage under this module name. - go.uber.org/zap -> github.com/luxfi/log, so common.Logger takes ...log.Field. zap.Error maps to log.Err: log.Error is luxfi/log's package-level logging function, not a field constructor, and the compiler is the only thing that catches that. Needs luxfi/log v1.6.1 for the Stringers constructor. - avalanchego/ -> host/. The package holds NodeID, VMBlock, Bitmask and size limits — the host node's types, vendored to avoid importing a whole node — so it is named for what it holds. Renaming it luxd/ would have swapped one brand for another and said just as little. - testutil/logger.go reimplemented without zapcore. Upstream layers a keyword-filtering Core, a debug-swallowing Encoder and a Tee because that is zap's extension model; luxfi/log has no such seam, so every policy is applied in one emit. That also fixes two defects the layering caused: SilenceExceptKeywords rebuilt the logger and discarded an installed Intercept hook, and the two sinks read different env vars (LOG_LEVEL vs log_level) so they disagreed about suppressing debug. Hooks run outside the lock, so a hook that logs fails the test instead of deadlocking it. Fatal panics rather than exiting, because exiting takes the suite down with no attribution. - simplex/monitor_test.go keeps a local logger: testutil imports simplex, so an internal test cannot import testutil back without closing a cycle. - README keeps the name Simplex throughout — it is the protocol's own name and the subject of reference [1]. Only the deployment target changed. The HyperSDK sentence still says Avalanche because that sentence is true. - Drops the fork's Makefile: it duplicated unit-tests.sh and fuzz.sh, and ran the suite with -timeout 30s when simplex alone needs over 100s. Co-authored-by: Hanzo Dev <[email protected]>
108 lines
2.1 KiB
Go
108 lines
2.1 KiB
Go
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package common
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/luxfi/log"
|
|
)
|
|
|
|
type BasicScheduler struct {
|
|
logger Logger
|
|
|
|
mu sync.Mutex
|
|
closed bool
|
|
running sync.WaitGroup
|
|
tasks chan Task
|
|
}
|
|
|
|
func NewScheduler(logger Logger, maxTasks uint64) *BasicScheduler {
|
|
s := &BasicScheduler{
|
|
logger: logger,
|
|
tasks: make(chan Task, maxTasks),
|
|
}
|
|
|
|
s.logger.Debug("Created Scheduler", log.Uint64("maxTasks", maxTasks))
|
|
|
|
s.running.Add(1)
|
|
go s.run()
|
|
|
|
return s
|
|
}
|
|
|
|
func (as *BasicScheduler) Size() int {
|
|
return len(as.tasks)
|
|
}
|
|
|
|
func (as *BasicScheduler) Close() {
|
|
as.mu.Lock()
|
|
if as.closed {
|
|
as.mu.Unlock()
|
|
return
|
|
}
|
|
as.closed = true
|
|
close(as.tasks)
|
|
as.mu.Unlock()
|
|
|
|
// we cannot hold the lock while waiting for the scheduler to finish,
|
|
// otherwise [scheduler.schedule] will be blocked trying to acquire the lock
|
|
as.running.Wait()
|
|
}
|
|
|
|
func (as *BasicScheduler) run() {
|
|
defer as.running.Done()
|
|
for task := range as.tasks {
|
|
as.mu.Lock()
|
|
closed := as.closed
|
|
as.mu.Unlock()
|
|
if closed {
|
|
return
|
|
}
|
|
as.logger.Debug("Running task", log.Int("remaining ready tasks", len(as.tasks)))
|
|
id := task()
|
|
as.logger.Debug("Task finished execution", log.Stringer("taskID", id))
|
|
}
|
|
}
|
|
|
|
func (as *BasicScheduler) Schedule(task Task) {
|
|
as.mu.Lock()
|
|
defer as.mu.Unlock()
|
|
|
|
if as.closed {
|
|
return
|
|
}
|
|
|
|
as.logger.Debug("Scheduling new ready task", log.Int("ready tasks", len(as.tasks)+1))
|
|
select {
|
|
case as.tasks <- task:
|
|
default:
|
|
as.logger.Warn("Scheduler task queue is full; task was not scheduled")
|
|
}
|
|
}
|
|
|
|
// ScheduleOrReplace schedules a task, replacing any queued task if full.
|
|
// The cancel function is called before draining the old task.
|
|
func (as *BasicScheduler) ScheduleOrReplace(task Task) {
|
|
as.mu.Lock()
|
|
defer as.mu.Unlock()
|
|
|
|
if as.closed {
|
|
return
|
|
}
|
|
|
|
// Check if full while holding the lock
|
|
if len(as.tasks) == cap(as.tasks) {
|
|
as.logger.Debug("Scheduler full, draining oldest task")
|
|
select {
|
|
case <-as.tasks:
|
|
default:
|
|
}
|
|
}
|
|
|
|
as.tasks <- task
|
|
}
|
|
|
|
type Task func() Digest
|