Pipeline.Safety.RecursionGuard (pipeline v0.0.1)

View Source

Recursion protection and circular dependency detection for nested pipelines.

Provides safety mechanisms to prevent infinite recursion and detect circular dependencies in nested pipeline execution chains.

Summary

Functions

Build the execution chain from the current context up to the root.

Perform all safety checks for nested pipeline execution.

Check for circular dependencies in the execution chain.

Check if the current execution context violates recursion limits.

Count the total number of steps across all nested pipelines.

Create a new execution context for a nested pipeline.

Log safety check results with appropriate log level.

Types

check_result()

@type check_result() :: :ok | {:error, String.t()}

execution_context()

@type execution_context() :: %{
  nesting_depth: non_neg_integer(),
  pipeline_id: String.t(),
  parent_context: execution_context() | nil,
  step_count: non_neg_integer()
}

safety_limits()

@type safety_limits() :: %{
  max_depth: non_neg_integer(),
  max_total_steps: non_neg_integer()
}

Functions

build_execution_chain(context)

@spec build_execution_chain(execution_context()) :: [String.t()]

Build the execution chain from the current context up to the root.

Parameters

  • context: The current execution context

Returns

  • List of pipeline IDs in the execution chain

check_all_safety(pipeline_id, context)

@spec check_all_safety(String.t(), execution_context()) :: check_result()

Perform all safety checks for nested pipeline execution.

Parameters

  • pipeline_id: The ID of the pipeline about to be executed
  • context: The current execution context
  • limits: Safety limits configuration (optional)

Returns

  • :ok if all checks pass
  • {:error, message} if any check fails

check_all_safety(pipeline_id, context, limits)

@spec check_all_safety(String.t(), execution_context(), safety_limits()) ::
  check_result()

check_circular_dependency(pipeline_id, context)

@spec check_circular_dependency(String.t(), execution_context()) :: check_result()

Check for circular dependencies in the execution chain.

Parameters

  • pipeline_id: The ID of the pipeline about to be executed
  • context: The current execution context

Returns

  • :ok if no circular dependency detected
  • {:error, message} if circular dependency found

Examples

iex> context = %{pipeline_id: "parent", parent_context: nil}
iex> Pipeline.Safety.RecursionGuard.check_circular_dependency("child", context)
:ok

iex> parent = %{pipeline_id: "parent", parent_context: nil}
iex> child = %{pipeline_id: "child", parent_context: parent}
iex> Pipeline.Safety.RecursionGuard.check_circular_dependency("parent", child)
{:error, "Circular dependency detected: parent → child → parent"}

check_limits(context)

@spec check_limits(execution_context()) :: check_result()

Check if the current execution context violates recursion limits.

Parameters

  • context: The current execution context
  • limits: Safety limits configuration (optional)

Returns

  • :ok if all checks pass
  • {:error, message} if limits are exceeded

Examples

iex> context = %{nesting_depth: 2, pipeline_id: "test", parent_context: nil, step_count: 5}
iex> Pipeline.Safety.RecursionGuard.check_limits(context)
:ok

iex> context = %{nesting_depth: 15, pipeline_id: "test", parent_context: nil, step_count: 5}
iex> Pipeline.Safety.RecursionGuard.check_limits(context)
{:error, "Maximum nesting depth (10) exceeded: current depth is 15"}

check_limits(context, limits)

@spec check_limits(execution_context(), safety_limits()) :: check_result()

count_total_steps(context)

@spec count_total_steps(execution_context()) :: non_neg_integer()

Count the total number of steps across all nested pipelines.

Parameters

  • context: The current execution context

Returns

  • Total number of steps

create_execution_context(pipeline_id, parent_context \\ nil, step_count \\ 0)

@spec create_execution_context(
  String.t(),
  execution_context() | nil,
  non_neg_integer()
) ::
  execution_context()

Create a new execution context for a nested pipeline.

Parameters

  • pipeline_id: The ID of the pipeline
  • parent_context: The parent execution context (optional)
  • step_count: The number of steps in this pipeline (default: 0)

Returns

  • New execution context

log_safety_check(arg1, pipeline_id, context)

@spec log_safety_check(check_result(), String.t(), execution_context()) :: :ok

Log safety check results with appropriate log level.

Parameters

  • check_result: The result of safety checks
  • pipeline_id: The ID of the pipeline being checked
  • context: The current execution context