Documentation
¶
Index ¶
- Constants
- func CanTransition(from string, to string) bool
- func EnsureTransition(from string, to string) error
- func IsSuccessStatus(status string) bool
- func IsTerminalStatus(status string) bool
- func RecoverDag(cfg *config.Config, repo interfaces.AnalysisRepository, ...)
- func ResumeNodeStatusForRestart(status string, hasContainer bool) (string, bool)
- func SchedulerEventFilter(evt RuntimeEvent) bool
- func SortNodesByStartedAt(nodes []*types.AnalysisNode)
- type AnalysisEventSink
- type CacheDecision
- type CacheFacts
- type CachePolicy
- type CachePolicyRegistry
- type DagRuntimeEventNotifier
- type DagScheduler
- type EventRouter
- type EventSinkFilter
- type NodeArtifactFingerprinter
- type NodeCompletionCoordinator
- type NodeContainerOperator
- type NodeDispatcher
- type NodeFailureCleanupFunc
- type NodeStopSweeper
- type PreparerFingerprinter
- type RerunAllPolicy
- type ReuseExistingPolicy
- type RunningEntry
- type RunningRegistry
- func (r *RunningRegistry) Get(analysisID int64) *RunningEntry
- func (r *RunningRegistry) IsRunning(analysisID int64) bool
- func (r *RunningRegistry) IsStopping(analysisID int64) bool
- func (r *RunningRegistry) MarkFinished(analysisID int64, status string)
- func (r *RunningRegistry) Register(entry *RunningEntry)
- func (r *RunningRegistry) RequestStop(analysisID int64) bool
- type RuntimeEngine
- func (e *RuntimeEngine) ClaimNextReadyNode(ctx context.Context, analysisID int64) (*types.AnalysisNode, error)
- func (e *RuntimeEngine) CompleteNode(ctx context.Context, analysisNodeID int64, status string, ...) (*types.AnalysisNode, error)
- func (e *RuntimeEngine) GetSnapshot(ctx context.Context, analysisID int64) (*RuntimeSnapshot, error)
- func (e *RuntimeEngine) MarkNodeRunning(ctx context.Context, analysisNodeID int64) (*types.AnalysisNode, error)
- func (e *RuntimeEngine) RefreshReadyStatus(ctx context.Context, analysisID int64) error
- type RuntimeEvent
- type RuntimeSnapshot
- type SchedulerConfig
- type SchedulerResult
- type ScriptAndParamsFingerprintPolicy
- type ScriptFingerprintPolicy
- type WorkerPool
Constants ¶
const ( EventDagStarted = "dag.started" EventDagCompleted = "dag.completed" EventDagFailed = "dag.failed" EventNodeSubmitted = "dag.node.submitted" EventNodeRunning = "dag.node.running" EventNodeCompleted = "dag.node.completed" EventNodeFailed = "dag.node.failed" EventNodeStateChange = "dag.node.state_changed" )
const ( StatusPending = "pending" StatusReady = "ready" StatusSubmitted = "submitted" StatusRunning = "running" StatusStopping = "stopping" StatusStopped = "stopped" StatusDone = "done" StatusFailed = "failed" StatusCached = "cached" StatusSkipped = "skipped" )
const ReasonStoppedByUser = "dag stopped by user"
ReasonStoppedByUser is the standard stop reason written to node error_message, shared so every scheduler reports the same text for a user-requested stop.
Variables ¶
This section is empty.
Functions ¶
func CanTransition ¶
func EnsureTransition ¶
func IsSuccessStatus ¶
func IsTerminalStatus ¶
func RecoverDag ¶ added in v0.1.4
func RecoverDag( cfg *config.Config, repo interfaces.AnalysisRepository, schedulers *scheduler.Registry, )
RecoverDag is the single recovery entry for every DAG scheduler.
It scans job_status running/stopping analyses in a background goroutine and hands each one back to the scheduler that owns it, resolved from analysis.scheduler_mode through the shared registry. Because ownership is a property of the analysis, one analysis can never be advanced by two schedulers at the same time.
Each orchestrator's RecoverRunningAnalyses handles a single analysis: running triggers a resume, stopping converges the stop request, so this loop does not need a separate cycle per job status.
func ResumeNodeStatusForRestart ¶ added in v0.1.4
ResumeNodeStatusForRestart decides how an in-flight node should be treated after the owning process restarted.
It is shared by every scheduler that resumes work from the analysis_nodes table (legacy DagOrchestrator and the dynamic V2 orchestrator) so that restart semantics stay identical across scheduling paths.
Return values:
- (StatusReady, true): the node lost its runner, it must be re-dispatched.
- ("", false): keep the current status. This covers nodes that were never in-flight, and running nodes whose container is still alive — those are expected to be finalized by deferred reconciliation instead.
func SchedulerEventFilter ¶ added in v0.1.4
func SchedulerEventFilter(evt RuntimeEvent) bool
SchedulerEventFilter is the delivery whitelist for dynamic scheduler sinks.
Only node terminal transitions can change dependency state, so only they can produce new schedulable work. Everything else the bus carries for the same analysis - node.submitted (the scheduler's own echo from pumpReadyQueue), node.running, node.state_changed, and the dag.* lifecycle events the scheduler publishes to itself - would only wake the loop for a no-op iteration that re-reads the runtime snapshot. Dropping them before the buffer also keeps the 256-entry window free for the events that actually matter.
This only narrows what a sink receives; the bus is untouched, so other subscribers (for example the realtime notifier) still observe every event.
func SortNodesByStartedAt ¶
func SortNodesByStartedAt(nodes []*types.AnalysisNode)
Types ¶
type AnalysisEventSink ¶ added in v0.1.4
type AnalysisEventSink struct {
// contains filtered or unexported fields
}
AnalysisEventSink is the per-analysis runtime event mailbox owned by one running scheduler.
Its lifetime matches exactly one scheduler run: EventRouter.Register creates it when a run is accepted and EventRouter.Unregister retires it when the run goroutine exits.
Design notes:
- The events channel is never closed. Retiring is signalled through the `closed` flag instead, which removes the classic "send on closed channel" race between the bus worker goroutine and the scheduler teardown.
- Enqueue is non-blocking by contract because it runs on the shared bus worker goroutine.
func NewAnalysisEventSink ¶ added in v0.1.4
func NewAnalysisEventSink() *AnalysisEventSink
NewAnalysisEventSink builds a detached sink that accepts every runtime event.
Schedulers normally obtain their sink from EventRouter.Register. This constructor exists for tests and for schedulers that run without a registered router.
func (*AnalysisEventSink) ConsumeDirty ¶ added in v0.1.4
func (s *AnalysisEventSink) ConsumeDirty() bool
ConsumeDirty reports whether events may have been lost, clearing the flag.
func (*AnalysisEventSink) Enqueue ¶ added in v0.1.4
func (s *AnalysisEventSink) Enqueue(evt RuntimeEvent)
Enqueue delivers one runtime event without ever blocking the caller.
Events rejected by the sink's keep predicate are dropped before they can take a buffer slot, so they neither displace a real event nor trip the overflow path.
func (*AnalysisEventSink) Events ¶ added in v0.1.4
func (s *AnalysisEventSink) Events() <-chan RuntimeEvent
Events exposes the receive side of the event mailbox.
A nil sink returns a nil channel so a select arm on it blocks forever instead of panicking; callers are expected to have substituted a live sink.
func (*AnalysisEventSink) Wake ¶ added in v0.1.4
func (s *AnalysisEventSink) Wake() <-chan struct{}
Wake exposes the overflow wake signal. It is closed-never and only ever carries a single pending notification.
type CacheDecision ¶ added in v0.1.4
type CacheDecision struct {
// Rerun requests re-materialization of the node as ready.
Rerun bool
// Reason is persisted on the node for observability.
Reason string
}
CacheDecision tells the reconciler whether the existing node must rerun.
type CacheFacts ¶ added in v0.1.4
type CacheFacts struct {
// CacheType is the analysis cache_type that selected the policy.
CacheType int
// Existing is the node persisted by a previous run.
Existing *types.AnalysisNode
// ProbeCommandMD5 is the fingerprint of the run script that would run now.
// It is only populated when the policy asks for a fingerprint.
ProbeCommandMD5 string
// ProbeParamsMD5 is the fingerprint of the params payload that would be used.
ProbeParamsMD5 string
}
CacheFacts is the immutable input of a cache policy decision.
type CachePolicy ¶ added in v0.1.4
type CachePolicy interface {
// Name is a stable identifier used in logs and diagnostics.
Name() string
// ResetsGraph reports whether this cache type invalidates the whole persisted
// graph before a run.
//
// It is the analysis-level half of a cache type, and the only place a reset may be
// requested from: Decide below is always called with a node that survived that
// reset, so a per-node rerun answer can never be mistaken for a graph-level one.
ResetsGraph() bool
// RequiresFingerprint reports whether Decide needs the probe fingerprints.
RequiresFingerprint() bool
// Decide returns the rerun decision for an already persisted node.
Decide(facts CacheFacts) CacheDecision
}
CachePolicy is the Strategy implementation behind analysis.cache_type.
Implementations must be stateless (they may be shared across runs) and must not perform I/O: the reconciler prepares fingerprints and hands them over.
type CachePolicyRegistry ¶ added in v0.1.4
type CachePolicyRegistry struct {
// contains filtered or unexported fields
}
CachePolicyRegistry resolves a CachePolicy per analysis cache type.
func NewCachePolicyRegistry ¶ added in v0.1.4
func NewCachePolicyRegistry() *CachePolicyRegistry
NewCachePolicyRegistry builds the default registry covering every cache type declared in types.Analysis.
func (*CachePolicyRegistry) Register ¶ added in v0.1.4
func (r *CachePolicyRegistry) Register(cacheType int, policy CachePolicy)
Register binds a policy to a cache type, replacing any previous entry.
func (*CachePolicyRegistry) Resolve ¶ added in v0.1.4
func (r *CachePolicyRegistry) Resolve(cacheType int) CachePolicy
Resolve returns the policy for cacheType, falling back to the safe default.
func (*CachePolicyRegistry) ShouldResetGraph ¶ added in v0.1.4
func (r *CachePolicyRegistry) ShouldResetGraph(cacheType int) bool
ShouldResetGraph reports whether cacheType invalidates the whole persisted graph before a run.
It is the analysis-level counterpart of the per-node policies: only rerun_all resets the graph, while every reuse policy keeps it and defers its decision to per-node reuse time.
type DagRuntimeEventNotifier ¶
type DagRuntimeEventNotifier struct {
// contains filtered or unexported fields
}
DagRuntimeEventNotifier subscribes DAG runtime events and pushes UI action messages to project users through the unified realtime hub.
func NewDagRuntimeEventNotifier ¶
func NewDagRuntimeEventNotifier(db *gorm.DB, projectRepo interfaces.ProjectRepository, analysisRepo interfaces.AnalysisRepository, hub *realtime.Hub) *DagRuntimeEventNotifier
func (*DagRuntimeEventNotifier) Handle ¶
func (n *DagRuntimeEventNotifier) Handle(evt event.Event)
type DagScheduler ¶
type DagScheduler struct {
// contains filtered or unexported fields
}
func NewDagScheduler ¶
func NewDagScheduler(analysisID int64, runtime *RuntimeEngine, dispatcher *NodeDispatcher, bus event.Bus, cfg SchedulerConfig) *DagScheduler
func (*DagScheduler) Run ¶
func (s *DagScheduler) Run(ctx context.Context) (*SchedulerResult, error)
type EventRouter ¶ added in v0.1.4
type EventRouter struct {
// contains filtered or unexported fields
}
EventRouter is the single long-lived event.Bus subscriber for the whole process. It routes RuntimeEvent values to the sink of the owning analysis.
Why a router instead of per-run subscriptions:
- A per-run bus.Subscribe adds a permanent subscriber goroutine per run because event.Bus has no Unsubscribe.
- OrderedMemoryBus.Publish writes to every subscriber queue with a blocking send, so the blocking surface grows linearly with the number of concurrent runs and every subscriber is woken by every other analysis' events.
With the router there is exactly one subscriber and routing is an O(1) map lookup.
The instance is created once by the DI container (internal/container) and injected into every scheduler that needs runtime events.
func NewEventRouter ¶ added in v0.1.4
func NewEventRouter() *EventRouter
NewEventRouter builds an empty router. The caller is responsible for subscribing it to the event bus exactly once.
func (*EventRouter) Handle ¶ added in v0.1.4
func (r *EventRouter) Handle(evt event.Event)
Handle implements event.Handler.
It must stay O(1) and strictly non-blocking: a slow or wedged analysis must never stall the shared bus worker or any other subscriber.
func (*EventRouter) Register ¶ added in v0.1.4
func (r *EventRouter) Register(analysisID int64) *AnalysisEventSink
Register creates the sink for analysisID, or returns the existing one when the analysis is already registered. The sink accepts every runtime event.
func (*EventRouter) RegisterWithFilter ¶ added in v0.1.4
func (r *EventRouter) RegisterWithFilter(analysisID int64, keep EventSinkFilter) *AnalysisEventSink
RegisterWithFilter is Register plus a delivery filter: the sink only ever receives events for which keep returns true. A nil keep accepts everything, which is exactly Register's behaviour.
Filtering happens before the buffer, so filtered-out events never occupy a slot and the scheduler loop is never woken for them. The bus itself is not touched, so other subscribers still see every event.
func (*EventRouter) Unregister ¶ added in v0.1.4
func (r *EventRouter) Unregister(analysisID int64)
Unregister retires and removes the sink for analysisID. It is safe to call more than once and safe to call for an unknown analysis.
The map entry is removed before retiring so a concurrent Register for the same analysis always obtains a fresh, live sink.
type EventSinkFilter ¶ added in v0.1.4
type EventSinkFilter func(RuntimeEvent) bool
EventSinkFilter decides whether a runtime event is worth delivering to a sink.
It runs on the shared bus worker goroutine, so it must stay cheap and must never block.
type NodeArtifactFingerprinter ¶ added in v0.1.4
type NodeArtifactFingerprinter interface {
// Fingerprint materializes the node artifacts and fills in CommandMD5 / ParamsMD5.
Fingerprint(ctx context.Context, node *types.AnalysisNode) error
}
NodeArtifactFingerprinter predicts a node's runtime artifacts and records their digests on the node.
It is deliberately narrower than prepare.NodeRuntimePreparer: a scheduler only needs the digests to decide whether a persisted node can be reused, it must not own execution-time preparation (output cleanup, script symlinks, ...) which stays with the dispatcher. Depending on the full preparer here is what made every materialized node look like it had to be prepared by the scheduler too.
It is shared by every scheduler that runs the fingerprint cache policies (dynamic V2 and dataflow V3), so a probe is always rendered the same way no matter which scheduler evaluates the cache.
type NodeCompletionCoordinator ¶
type NodeCompletionCoordinator struct {
// contains filtered or unexported fields
}
func NewNodeCompletionCoordinator ¶
func NewNodeCompletionCoordinator( analysisRepo interfaces.AnalysisRepository, containerRepo interfaces.ContainerRepository, containerOps NodeContainerOperator, bus event.Bus, cfg *config.Config, ) *NodeCompletionCoordinator
func (*NodeCompletionCoordinator) Handle ¶
func (c *NodeCompletionCoordinator) Handle(evt event.Event)
type NodeContainerOperator ¶
type NodeDispatcher ¶
type NodeDispatcher struct {
// contains filtered or unexported fields
}
func NewNodeDispatcher ¶
func NewNodeDispatcher( repo interfaces.AnalysisRepository, bus event.Bus, factory *executor.ExecuterFactory, preparer prepare.NodeRuntimePreparer, ) *NodeDispatcher
func (*NodeDispatcher) Dispatch ¶
func (d *NodeDispatcher) Dispatch(ctx context.Context, analysisNodeID int64) error
func (*NodeDispatcher) Stop ¶
func (d *NodeDispatcher) Stop(ctx context.Context, node *types.AnalysisNode) (*executor.Result, error)
type NodeFailureCleanupFunc ¶
type NodeFailureCleanupFunc func(ctx context.Context, node *types.AnalysisNode)
type NodeStopSweeper ¶ added in v0.1.4
type NodeStopSweeper struct {
// contains filtered or unexported fields
}
NodeStopSweeper owns "stop the nodes of one analysis", the single implementation shared by every scheduler (legacy dag, dynamic, dataflow).
Before this type existed each orchestrator carried its own copy of the stop sequence, and they had already drifted apart (one wrote failed, another stopped, and none of them stopped the containers). Keeping one implementation means the meaning of "a stopped analysis" cannot depend on which scheduler happened to run.
It is stateless apart from its timeout, so one instance can be shared across concurrent runs of different analyses.
func NewNodeStopSweeper ¶ added in v0.1.4
func NewNodeStopSweeper(repo interfaces.AnalysisRepository, dispatcher *NodeDispatcher) *NodeStopSweeper
NewNodeStopSweeper builds the shared stop helper. A nil dispatcher is tolerated: the sweep then only latches node state instead of failing every call.
func (*NodeStopSweeper) MarkNodesStopped ¶ added in v0.1.4
func (s *NodeStopSweeper) MarkNodesStopped(ctx context.Context, analysisID int64, reason string) error
MarkNodesStopped terminalizes every non-terminal node of the analysis.
It is the mandatory last step of a stop: the analysis is about to be written as a terminal stopped state, and recovery only scans running/stopping analyses, so a node left in "stopping" would never be looked at again. Without this the node would wait forever for a container stop event that may never arrive.
func (*NodeStopSweeper) StopActiveNodes ¶ added in v0.1.4
func (s *NodeStopSweeper) StopActiveNodes(ctx context.Context, analysisID int64, reason string)
StopActiveNodes stops every node of the analysis that is still in flight: it first persists "stopping" (the stop latch), then asks the executor to stop the real process or container behind the node.
The ordering matters. Persisting "stopping" first is what makes the stop convergent even if something is still dispatching: the claim query only ever selects ready rows, and a dispatch that already claimed the node fails the running transition instead of creating a container. Only then is it meaningful to stop containers, because from here on nothing new can appear behind our back.
Only running/submitted nodes are handled: ready/pending nodes never reached an executor, so there is nothing to stop and they are left to MarkNodesStopped. A single failing node is logged, never propagated: the remaining nodes still have containers that must be told to stop.
type PreparerFingerprinter ¶ added in v0.1.4
type PreparerFingerprinter struct {
// contains filtered or unexported fields
}
PreparerFingerprinter adapts the runtime preparer to the scheduler-side fingerprinting contract.
The preparer stays the single source of truth for run.sh / params.json rendering, so a scheduler borrows it to predict the artifacts instead of re-implementing the rendering rules (and drifting from the dispatcher).
func NewPreparerFingerprinter ¶ added in v0.1.4
func NewPreparerFingerprinter(preparer prepare.NodeRuntimePreparer) *PreparerFingerprinter
NewPreparerFingerprinter wraps a NodeRuntimePreparer.
func (*PreparerFingerprinter) Fingerprint ¶ added in v0.1.4
func (f *PreparerFingerprinter) Fingerprint(ctx context.Context, node *types.AnalysisNode) error
Fingerprint implements NodeArtifactFingerprinter.
Output cleanup is explicitly disabled: a probe runs for nodes that may well be reused as-is, and wiping their output directory would delete the results the downstream nodes still reference. The dispatcher cleans the output directory when it prepares the node for an actual execution.
type RerunAllPolicy ¶ added in v0.1.4
type RerunAllPolicy struct{}
RerunAllPolicy implements types.CacheTypeRerunAll.
rerun_all is an analysis-level strategy: it is expressed by resetting the persisted graph before the run (ResetsGraph), so every node is materialized from scratch.
Per node there is therefore nothing left to disable, and Decide keeps whatever result is reusable - exactly like ReuseExistingPolicy. A node can only still be persisted when the reset was deliberately skipped, which is precisely the resume path, where a restart must not turn into a full rerun from scratch.
Answering "rerun" unconditionally here livelocks a run: the reconciler re-decides every persisted node on every pass, including the nodes this very run has just completed, so each success is immediately flipped back to ready and the graph never reaches a terminal state.
func (RerunAllPolicy) Decide ¶ added in v0.1.4
func (RerunAllPolicy) Decide(facts CacheFacts) CacheDecision
Decide implements CachePolicy.
func (RerunAllPolicy) Name ¶ added in v0.1.4
func (RerunAllPolicy) Name() string
Name implements CachePolicy.
func (RerunAllPolicy) RequiresFingerprint ¶ added in v0.1.4
func (RerunAllPolicy) RequiresFingerprint() bool
RequiresFingerprint implements CachePolicy.
func (RerunAllPolicy) ResetsGraph ¶ added in v0.1.4
func (RerunAllPolicy) ResetsGraph() bool
ResetsGraph implements CachePolicy.
type ReuseExistingPolicy ¶ added in v0.1.4
type ReuseExistingPolicy struct{}
ReuseExistingPolicy keeps whatever is persisted (types.CacheTypeReuseExistingNode).
func (ReuseExistingPolicy) Decide ¶ added in v0.1.4
func (ReuseExistingPolicy) Decide(facts CacheFacts) CacheDecision
Decide implements CachePolicy.
func (ReuseExistingPolicy) Name ¶ added in v0.1.4
func (ReuseExistingPolicy) Name() string
Name implements CachePolicy.
func (ReuseExistingPolicy) RequiresFingerprint ¶ added in v0.1.4
func (ReuseExistingPolicy) RequiresFingerprint() bool
RequiresFingerprint implements CachePolicy.
func (ReuseExistingPolicy) ResetsGraph ¶ added in v0.1.4
func (ReuseExistingPolicy) ResetsGraph() bool
ResetsGraph implements CachePolicy.
type RunningEntry ¶
type RunningRegistry ¶
type RunningRegistry struct {
// contains filtered or unexported fields
}
func NewRunningRegistry ¶
func NewRunningRegistry() *RunningRegistry
func (*RunningRegistry) Get ¶ added in v0.1.4
func (r *RunningRegistry) Get(analysisID int64) *RunningEntry
Get returns a read-only copy of the running entry for the analysis. The copy has its Cancel func cleared so callers can only inspect state.
func (*RunningRegistry) IsRunning ¶
func (r *RunningRegistry) IsRunning(analysisID int64) bool
func (*RunningRegistry) IsStopping ¶
func (r *RunningRegistry) IsStopping(analysisID int64) bool
func (*RunningRegistry) MarkFinished ¶
func (r *RunningRegistry) MarkFinished(analysisID int64, status string)
func (*RunningRegistry) Register ¶
func (r *RunningRegistry) Register(entry *RunningEntry)
func (*RunningRegistry) RequestStop ¶
func (r *RunningRegistry) RequestStop(analysisID int64) bool
type RuntimeEngine ¶
type RuntimeEngine struct {
// contains filtered or unexported fields
}
func NewRuntimeEngine ¶
func NewRuntimeEngine(repo interfaces.AnalysisRepository) *RuntimeEngine
func (*RuntimeEngine) ClaimNextReadyNode ¶
func (e *RuntimeEngine) ClaimNextReadyNode(ctx context.Context, analysisID int64) (*types.AnalysisNode, error)
func (*RuntimeEngine) CompleteNode ¶
func (*RuntimeEngine) GetSnapshot ¶
func (e *RuntimeEngine) GetSnapshot(ctx context.Context, analysisID int64) (*RuntimeSnapshot, error)
func (*RuntimeEngine) MarkNodeRunning ¶
func (e *RuntimeEngine) MarkNodeRunning(ctx context.Context, analysisNodeID int64) (*types.AnalysisNode, error)
func (*RuntimeEngine) RefreshReadyStatus ¶
func (e *RuntimeEngine) RefreshReadyStatus(ctx context.Context, analysisID int64) error
type RuntimeEvent ¶
type RuntimeEvent struct {
Name string `json:"name"`
AnalysisID int64 `json:"analysis_id,string"`
AnalysisNodeID int64 `json:"analysis_node_id,string,omitempty"`
NodeID string `json:"node_id,omitempty"`
OccurredAt time.Time `json:"occurred_at"`
Payload map[string]interface{} `json:"payload,omitempty"`
}
type RuntimeSnapshot ¶
type RuntimeSnapshot struct {
AnalysisID int64 `json:"analysis_id,string"`
TotalNodes int `json:"total_nodes"`
StatusCount map[string]int `json:"status_count"`
CompletedCount int `json:"completed_count"`
CompletionPercent int `json:"completion_percent"`
ReadyCount int `json:"ready_count"`
RunningCount int `json:"running_count"`
IsFinished bool `json:"is_finished"`
}
type SchedulerConfig ¶
type SchedulerResult ¶
type SchedulerResult struct {
AnalysisID int64 `json:"analysis_id"`
SubmittedCount int `json:"submitted_count"`
FailedToSubmitCount int `json:"failed_to_submit_count"`
TimedOut bool `json:"timed_out"`
Snapshot *RuntimeSnapshot `json:"snapshot"`
}
type ScriptAndParamsFingerprintPolicy ¶ added in v0.1.4
type ScriptAndParamsFingerprintPolicy struct{}
ScriptAndParamsFingerprintPolicy reruns when either the generated run script or the params payload changed (types.CacheTypeReuseWhenScriptAndParamsUnchanged).
func (ScriptAndParamsFingerprintPolicy) Decide ¶ added in v0.1.4
func (ScriptAndParamsFingerprintPolicy) Decide(facts CacheFacts) CacheDecision
Decide implements CachePolicy.
func (ScriptAndParamsFingerprintPolicy) Name ¶ added in v0.1.4
func (ScriptAndParamsFingerprintPolicy) Name() string
Name implements CachePolicy.
func (ScriptAndParamsFingerprintPolicy) RequiresFingerprint ¶ added in v0.1.4
func (ScriptAndParamsFingerprintPolicy) RequiresFingerprint() bool
RequiresFingerprint implements CachePolicy.
func (ScriptAndParamsFingerprintPolicy) ResetsGraph ¶ added in v0.1.4
func (ScriptAndParamsFingerprintPolicy) ResetsGraph() bool
ResetsGraph implements CachePolicy.
type ScriptFingerprintPolicy ¶ added in v0.1.4
type ScriptFingerprintPolicy struct{}
ScriptFingerprintPolicy reruns when the generated run script changed (types.CacheTypeReuseWhenScriptUnchanged).
func (ScriptFingerprintPolicy) Decide ¶ added in v0.1.4
func (ScriptFingerprintPolicy) Decide(facts CacheFacts) CacheDecision
Decide implements CachePolicy.
func (ScriptFingerprintPolicy) Name ¶ added in v0.1.4
func (ScriptFingerprintPolicy) Name() string
Name implements CachePolicy.
func (ScriptFingerprintPolicy) RequiresFingerprint ¶ added in v0.1.4
func (ScriptFingerprintPolicy) RequiresFingerprint() bool
RequiresFingerprint implements CachePolicy.
func (ScriptFingerprintPolicy) ResetsGraph ¶ added in v0.1.4
func (ScriptFingerprintPolicy) ResetsGraph() bool
ResetsGraph implements CachePolicy.
type WorkerPool ¶
type WorkerPool struct {
// contains filtered or unexported fields
}
func NewWorkerPool ¶
func NewWorkerPool(dispatcher *NodeDispatcher, workers int, queueSize int) *WorkerPool
func (*WorkerPool) Cap ¶ added in v0.1.4
func (p *WorkerPool) Cap() int
Cap reports the pool queue capacity, used by callers as their claim-ahead and backpressure limit.
func (*WorkerPool) Enqueue ¶
func (p *WorkerPool) Enqueue(nodeID int64) bool
Enqueue is the non-blocking variant: it reports false when the queue has no room left, leaving the retry/backpressure policy to the caller.
func (*WorkerPool) EnqueueWait ¶ added in v0.1.4
func (p *WorkerPool) EnqueueWait(ctx context.Context, nodeID int64) bool
EnqueueWait blocks until nodeID is queued, ctx is cancelled, or the pool stops, and reports whether the node made it into the queue.
It must only be called from the goroutine that owns the pool lifecycle (the one that calls Stop). Stop closes the job channel, and a send on a closed channel panics in select even from the default branch, so a sender running on another goroutine could always race with Stop.
func (*WorkerPool) QueueLen ¶
func (p *WorkerPool) QueueLen() int
func (*WorkerPool) Start ¶
func (p *WorkerPool) Start(ctx context.Context)
func (*WorkerPool) Stop ¶
func (p *WorkerPool) Stop()
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package orchestratorv2 implements the dynamic (Nextflow-like) DAG scheduler used by gobrave analyses.
|
Package orchestratorv2 implements the dynamic (Nextflow-like) DAG scheduler used by gobrave analyses. |