iop/apps/node/internal/node/node.go
toki f9442edfef feat(runtime): provider liveness 복구를 완성한다
장시간 무응답 attempt를 안전하게 fence하고 provider health와 분리 관측해야 중복 출력 없이 기존 recovery budget으로 재실행할 수 있다.
2026-08-06 08:49:59 +09:00

74 lines
2.4 KiB
Go

// Package node is the core IOP Node service. It implements
// transport.Handler and orchestrates routing → adapter execution.
package node
import (
"io"
"os"
"sync"
"go.uber.org/zap"
"iop/apps/node/internal/adapters"
"iop/apps/node/internal/store"
"iop/packages/go/credentiallease"
runtime "iop/packages/go/execution"
)
// Node implements transport.Handler and coordinates the full execution pipeline.
type Node struct {
nodeID string
router runtime.Router
store *store.Store
runs *runManager
globalGate *fifoGate // node-wide concurrency safety guard across all adapters (retained for compatibility; not used for admission)
adapterGatesMu sync.Mutex
adapterGates map[string]*fifoGate // per adapter-key concurrency safety guard
out io.Writer
logger *zap.Logger
currentConfigSet *adapters.ConfigSet
configSetMu sync.RWMutex
credentialConsumer *credentiallease.Consumer
watchdogClock attemptClock
// liveness is the bounded stall-observability observer. Production Nodes
// share one process-global collector set; tests inject an isolated registry
// via the test-only constructor path in liveness_observability.go.
liveness *nodeLivenessObserver
}
func (n *Node) SetCredentialConsumer(consumer *credentiallease.Consumer) {
n.credentialConsumer = consumer
}
// New creates a Node. It satisfies transport.Handler.
// globalConcurrency is retained as a compatibility argument but is no longer
// used for admission. Node-wide concurrency limits have been removed; per-
// adapter MaxConcurrency from Capabilities is the sole admission gate.
// out receives console debug output; pass os.Stdout for production, io.Discard in tests.
func New(
nodeID string,
router runtime.Router,
st *store.Store,
globalConcurrency int,
out io.Writer,
logger *zap.Logger,
initialConfigSet *adapters.ConfigSet,
) *Node {
if out == nil {
out = os.Stdout
}
return &Node{
nodeID: nodeID,
router: router,
store: st,
runs: newRunManager(),
globalGate: newFifoGate(globalConcurrency),
adapterGates: make(map[string]*fifoGate),
out: out,
logger: logger,
currentConfigSet: initialConfigSet,
watchdogClock: realAttemptClock{},
liveness: newProductionNodeLivenessObserver(logger),
}
}