BUCKYVERSE

Date: 2025-03-10

Status

Proposed

Context

The Codexis book building system needs a consistent approach to implementing builders for different output formats. The current pseudocode shows a need for specialized builders (PDF, EPUB, MOBI, KFX, WikiJS) that share common patterns but have format-specific requirements. We need to establish a standardized builder pattern that ensures:

  1. Consistent interface across all format builders
  2. Proper handling of format-specific requirements
  3. Integration with the validation system
  4. Efficient asset management
  5. Error handling and recovery
  6. Progress reporting

Decision

We will implement a comprehensive builder pattern with the following components:

1. Base Builder Behavior

defmodule Codexis.Builder do
  @callback build(content :: Content.t(), options :: Keyword.t()) :: {:ok, Output.t()} | {:error, term()}
  @callback validate(output :: Output.t()) :: :ok | {:error, term()}
  @callback cleanup(output :: Output.t()) :: :ok | {:error, term()}
  
  defmacro __using__(_opts) do
    quote do
      @behaviour Codexis.Builder
      
      alias Codexis.Content
      alias Codexis.Output
      alias Codexis.Assets
      
      def build(content, options \\ []) do
        with {:ok, validated_content} <- validate_content(content),
             {:ok, processed_assets} <- process_assets(content.assets),
             {:ok, output} <- do_build(validated_content, processed_assets, options),
             :ok <- validate(output) do
          {:ok, output}
        end
      end
      
      defp validate_content(content), do: Content.validate(content)
      defp process_assets(assets), do: Assets.process(assets)
      
      defoverridable [build: 2]
    end
  end
end

2. Format-Specific Builders

defmodule Codexis.Builders.PDFBuilder do
  use Codexis.Builder
  
  @impl true
  def do_build(content, assets, options) do
    # PDF-specific build logic
  end
  
  @impl true
  def validate(output) do
    # PDF-specific validation
  end
  
  @impl true
  def cleanup(output) do
    # PDF-specific cleanup
  end
end

defmodule Codexis.Builders.WikiJSBuilder do
  use Codexis.Builder
  
  @impl true
  def do_build(content, assets, options) do
    # WikiJS-specific build logic
  end
  
  @impl true
  def validate(output) do
    # WikiJS-specific validation
  end
  
  @impl true
  def cleanup(output) do
    # WikiJS-specific cleanup
  end
end

3. Common Builder Utilities

defmodule Codexis.BuilderUtils do
  def process_cover_image(image_path, format) do
    # Common cover image processing logic
  end
  
  def handle_assets(assets, format) do
    # Common asset handling logic
  end
  
  def apply_metadata(content, format) do
    # Common metadata application logic
  end
end

4. Builder Registry

defmodule Codexis.BuilderRegistry do
  use GenServer
  
  @builders %{
    pdf: Codexis.Builders.PDFBuilder,
    epub: Codexis.Builders.EPUBBuilder,
    mobi: Codexis.Builders.MOBIBuilder,
    kfx: Codexis.Builders.KFXBuilder,
    wikijs: Codexis.Builders.WikiJSBuilder
  }
  
  def get_builder(format) when is_atom(format) do
    Map.get(@builders, format)
  end
end

5. Progress Reporting

defmodule Codexis.BuildProgress do
  def report_progress(format, stage, percentage) do
    :telemetry.execute(
      [:codexis, :builder, :progress],
      %{percentage: percentage},
      %{format: format, stage: stage}
    )
  end
end

Consequences

Positive

  1. Consistency: All builders follow the same pattern and interface
  2. Extensibility: Easy to add new format builders
  3. Maintainability: Common functionality is shared through utilities
  4. Reliability: Built-in validation and error handling
  5. Observability: Integrated progress reporting and telemetry

Negative

  1. Complexity: More complex than simple functions
  2. Learning Curve: Developers need to understand the pattern
  3. Overhead: Some performance overhead from abstractions

Risks

  1. Performance Impact: Need to monitor builder abstraction overhead
  2. Resource Management: Must ensure proper cleanup across builders
  3. Error Propagation: Need to handle errors consistently

Compliance

Builders must:

  1. Implement all required callbacks
  2. Use provided utilities for common operations
  3. Report progress appropriately
  4. Handle cleanup properly
  5. Validate outputs before completion

Notes