Class: Kernai::TaskScheduler

Inherits:
Object
  • Object
show all
Defined in:
lib/kernai/task_scheduler.rb

Overview

Executes the tasks stored in a Context, respecting dependencies and parallelism flags. The scheduler is intentionally dumb: it has no knowledge of LLMs, agents or providers. A ‘runner` callable receives (task, context) and is expected to return the task result.

The scheduling strategy is read from ‘context.plan.strategy`:

  • “sequential” forces every ready task to run serially

  • “parallel” forces every ready task to run concurrently

  • “mixed” (default) honors each task’s own ‘parallel` flag

Defined Under Namespace

Classes: DeadlockError

Constant Summary collapse

STRATEGIES =
%w[sequential parallel mixed].freeze
DEFAULT_STRATEGY =
'mixed'

Instance Method Summary collapse

Constructor Details

#initialize(context, runner) ⇒ TaskScheduler

Returns a new instance of TaskScheduler.



21
22
23
24
25
# File 'lib/kernai/task_scheduler.rb', line 21

def initialize(context, runner)
  @context = context
  @runner = runner
  @strategy = resolve_strategy(context.plan&.strategy)
end

Instance Method Details

#runObject

Run all tasks until the graph is complete. Returns the final task_results hash.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/kernai/task_scheduler.rb', line 29

def run
  loop do
    ready = ready_tasks

    if ready.empty?
      pending = @context.tasks.reject(&:done?)
      raise DeadlockError, "Tasks could not complete: #{pending.map(&:id).join(', ')}" if pending.any?

      break
    end

    parallel, sequential = ready.partition { |t| effective_parallel?(t) }

    run_parallel(parallel) if parallel.any?
    run_sequential(sequential) if sequential.any?
  end

  @context.task_results
end