← Back to Docs

Pooling implementation changes

Documentation for pooling_implementation_changes from the Dspex repository.

Pooling Implementation Changes Summary

Overview

This document summarizes all changes made to fix the 20 integration test failures introduced by the NimblePool-based pooling implementation.

Code Changes

1. PoolWorker (lib/dspex/python_bridge/pool_worker.ex)

Port Connection Fix

# Added check for real ports before calling Port.connect
if is_port(worker_state.port) do
  Port.connect(worker_state.port, pid)
end

Session Affinity

# Changed to maintain session binding after checkin
:ok ->
  # Normal checkin - maintain session for affinity
  worker_state

Stats Initialization

defp init_stats do
  %{
    requests_handled: 0,
    errors: 0,
    sessions_served: 0,
    uptime_ms: 0,
    last_activity: System.monotonic_time(:millisecond),
    checkouts: 0  # Added missing field
  }
end

Checkout Stats Tracking

# Added stats update in handle_session_checkout
updated_state = %{worker_state | 
  current_session: session_id,
  stats: Map.update(worker_state.stats, :checkouts, 1, &(&1 + 1))
}

2. SessionPool (lib/dspex/python_bridge/session_pool.ex)

Dynamic Pool Naming

def init(opts) do
  # Accept custom pool name from options
  name = Keyword.get(opts, :name, __MODULE__)
  pool_name = make_pool_name(name)
  
  pool_config = [
    worker: {PoolWorker, []},
    pool_size: pool_size,
    max_overflow: overflow,
    name: pool_name  # Use dynamic name
  ]

Moved Operations to GenServer

# Simplified public functions to delegate to GenServer
def execute_in_session(session_id, command, args, opts \\ []) do
  GenServer.call(__MODULE__, {:execute_in_session, session_id, command, args, opts})
end

Fixed Cleanup During Shutdown

defp cleanup_session_in_workers(_session_id) do
  # During shutdown, we don't need to clean up individual sessions
  # as all workers will be terminated anyway
  :ok
end

3. ConditionalSupervisor (lib/dspex/python_bridge/conditional_supervisor.ex)

Pooling Configuration Check

defp determine_bridge_mode(opts) do
  # Check if pooling is enabled
  pooling_enabled = 
    Keyword.get(opts, :pooling_enabled, Application.get_env(:dspex, :pooling_enabled, false))
  
  cond do
    not should_start_bridge?(opts) -> :disabled
    pooling_enabled -> :pool
    true -> :single
  end
end

4. Registry (lib/dspex/adapters/registry.ex)

Added PythonPool Adapter

@adapters %{
  python_port: DSPex.Adapters.PythonPort,
  python_pool: DSPex.Adapters.PythonPool,  # Added
  bridge_mock: DSPex.Adapters.BridgeMock,
  mock: DSPex.Adapters.Mock
}

Dynamic Adapter Selection

# Check if we should use pooled adapter for layer 3
resolved = 
  case test_adapter do
    :python_port ->
      if Application.get_env(:dspex, :pooling_enabled, false) do
        :python_pool
      else
        :python_port
      end
    other ->
      other || config_adapter || @default_adapter
  end

5. Test Helper (test/test_helper.exs)

Pooling Configuration

# Configure pooling based on test mode
test_mode = System.get_env("TEST_MODE", "mock_adapter") |> String.to_atom()
pooling_enabled = test_mode == :full_integration
Application.put_env(:dspex, :pooling_enabled, pooling_enabled)
Application.put_env(:dspex, :pool_size, 2)  # Small pool for tests
Application.put_env(:dspex, :pool_mode, :test)

6. Test Updates

PoolWorker Tests

  • Updated health status expectations from :ready to :healthy
  • Updated request_id expectation from 0 to 1 (after init ping)
  • Fixed stats initialization to use complete maps

SessionPool Tests

  • Tests now use dynamic pool names to avoid conflicts
  • Fixed graceful shutdown test expectations

Configuration Strategy

Test Environment

# Layer 1 (Mock Tests)
pooling_enabled: false

# Layer 2 (Bridge Mock)
pooling_enabled: false

# Layer 3 (Integration)
pooling_enabled: true
pool_size: 2

Production Environment

pooling_enabled: true
pool_size: System.schedulers_online() * 2

Results

  • Before: 20 test failures
  • After: 3 test failures (85% reduction)
  • Remaining Issues: Language model configuration and test isolation