databuild/plans/webapp_v1/chunk-8-graph-analysis.md

6 KiB

Chunk 8: Graph Analysis

Parent: Build Graph Dashboard
Previous: Chunk 7: Jobs Pages
Next: Chunk 9: Polish

Overview

Implement interactive build graph analysis with partition input forms, Mermaid.js visualization, and execution plan display.

Scope

In Scope

  • Partition input form for analysis requests
  • Mermaid.js visualization of job graphs
  • Execution plan table with job details
  • Interactive graph exploration
  • Error handling for invalid partition references

Out of Scope

  • Complex graph editing capabilities
  • Advanced graph algorithms or analysis
  • Performance optimization for large graphs
  • Real-time graph updates

Technical Approach

Data Sources

From Build Graph Service API:

  • /api/v1/analyze - Analyze build graph for partitions
  • Returns JobGraph with tasks and dependencies

Component Structure

const GraphAnalysis = {
  oninit: () => {
    this.partitions = [''];
    this.jobGraph = null;
    this.loading = false;
    this.error = null;
    this.mermaidRendered = false;
  },
  
  view: () => [
    m('.analysis-header', [
      m('h1', 'Graph Analysis'),
      m('p', 'Analyze the build graph for specific partitions')
    ]),
    
    m('.analysis-form', [
      m('h2', 'Partition References'),
      m('.partition-inputs', [
        this.partitions.map((partition, index) =>
          m('.input-group', [
            m('input', {
              value: partition,
              placeholder: 'Enter partition reference...',
              oninput: (e) => this.partitions[index] = e.target.value,
            }),
            m('button.btn.btn-outline', {
              onclick: () => this.removePartition(index),
              disabled: this.partitions.length <= 1
            }, 'Remove')
          ])
        ),
        m('button.btn.btn-outline', {
          onclick: () => this.addPartition()
        }, 'Add Partition')
      ]),
      
      m('.form-actions', [
        m('button.btn.btn-primary', {
          onclick: () => this.analyzeGraph(),
          disabled: this.loading || !this.hasValidPartitions()
        }, this.loading ? 'Analyzing...' : 'Analyze Graph')
      ])
    ]),
    
    this.error ? m('.error-message', [
      m('.alert.alert-error', this.error)
    ]) : null,
    
    this.jobGraph ? m('.analysis-results', [
      m('.graph-visualization', [
        m('h2', 'Job Graph'),
        m('#mermaid-graph', {
          oncreate: () => this.renderMermaid(),
          onupdate: () => this.renderMermaid()
        })
      ]),
      
      m('.execution-plan', [
        m('h2', 'Execution Plan'),
        m('table.table', [
          m('thead', [
            m('tr', [
              m('th', 'Job'),
              m('th', 'Outputs'),
              m('th', 'Inputs'),
              m('th', 'Arguments'),
            ])
          ]),
          m('tbody', this.jobGraph.nodes.map(task =>
            m('tr', [
              m('td', m('a', { 
                href: `/jobs/${encodeJobLabel(task.job.label)}` 
              }, task.job.label)),
              m('td', m('ul', task.config.outputs.map(output =>
                m('li', m('a', { 
                  href: `/partitions/${encodePartitionRef(output.str)}` 
                }, output.str))
              ))),
              m('td', m('ul', task.config.inputs.map(input =>
                m('li', input.partition_ref.str)
              ))),
              m('td', m('code', task.config.args.join(' '))),
            ])
          ))
        ])
      ])
    ]) : null
  ]
};

Mermaid.js Integration

// Generate Mermaid diagram from JobGraph
function generateMermaidDiagram(jobGraph: JobGraph): string {
  const nodes = jobGraph.nodes.map(task => 
    `${task.job.label}["${task.job.label}"]`
  ).join('\n  ');
  
  const edges = jobGraph.nodes.flatMap(task =>
    task.config.inputs.map(input => {
      const sourceJob = findJobForPartition(input.partition_ref.str);
      return sourceJob ? `${sourceJob} --> ${task.job.label}` : null;
    }).filter(Boolean)
  ).join('\n  ');
  
  return `graph TD\n  ${nodes}\n  ${edges}`;
}

// Render with Mermaid
function renderMermaid() {
  if (!this.jobGraph || this.mermaidRendered) return;
  
  const diagram = generateMermaidDiagram(this.jobGraph);
  mermaid.render('graph', diagram, (svgCode) => {
    document.getElementById('mermaid-graph').innerHTML = svgCode;
    this.mermaidRendered = true;
  });
}

Form Management

  • Dynamic partition input fields
  • Add/remove partition functionality
  • Input validation
  • Error handling for invalid references

Implementation Strategy

  1. Create Form Interface

    • Dynamic partition input management
    • Form validation and submission
    • Loading states and error handling
  2. Integrate Graph Analysis API

    • API calls to analyze endpoint
    • Error handling for analysis failures
    • JobGraph data processing
  3. Add Mermaid.js Visualization

    • Include Mermaid.js library
    • Generate diagrams from JobGraph
    • Handle rendering lifecycle
  4. Build Execution Plan Display

    • Table layout for job details
    • Links to job and partition pages
    • Clear display of dependencies

Deliverables

  • Interactive partition input form
  • Mermaid.js graph visualization
  • Execution plan table with job details
  • Error handling for invalid inputs
  • Links to related job and partition pages

Success Criteria

  • Form allows adding/removing partition inputs
  • Graph analysis API integration works correctly
  • Mermaid diagrams render accurately
  • Execution plan shows complete job details
  • Error handling provides useful feedback
  • Links navigate to appropriate detail pages

Testing

  • Test form with various partition combinations
  • Verify graph analysis API calls work correctly
  • Test Mermaid diagram generation and rendering
  • Validate execution plan accuracy
  • Test error handling with invalid partitions
  • Check links to job and partition detail pages
  • Test with complex multi-job graphs