Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 19, 2026

The jqschema middleware was parsing the jq query on every request, violating gojq's documented best practice of "compile once, run many."

Changes

Pre-compile query at initialization

  • Move query compilation to package init() with fail-fast error handling
  • Store compiled *gojq.Code in package-level variable for reuse
  • Replace Parse() + Run() pattern with Compile() + RunWithContext()

Before:

func applyJqSchema(jsonData interface{}) (string, error) {
    query, err := gojq.Parse(jqSchemaFilter)  // Parse on every call
    if err != nil {
        return "", err
    }
    iter := query.Run(jsonData)
    // ...
}

After:

var jqSchemaCode *gojq.Code

func init() {
    query, _ := gojq.Parse(jqSchemaFilter)
    jqSchemaCode, _ = gojq.Compile(query)  // Compile once at startup
}

func applyJqSchema(ctx context.Context, jsonData interface{}) (string, error) {
    iter := jqSchemaCode.RunWithContext(ctx, jsonData)  // Reuse compiled code
    // ...
}

Add context support

  • Thread context.Context from HTTP handler to query execution
  • Enable timeout/cancellation via RunWithContext()

Enhance error handling

  • Type-check for *gojq.HaltError to distinguish clean halts from failures
  • Include exit codes in error messages

Benchmark suite

  • Validate 1.8-5.25x speedup across payload sizes (small: 5.25x, medium: 3.47x, large: 1.80x)
  • Document 55-83% reduction in memory allocations

Performance Impact

Payload Before (ns/op) After (ns/op) Speedup
Small 37,523 7,148 5.25x
Medium 42,209 12,161 3.47x
Large 60,304 33,546 1.80x
Original prompt

This section details on the original issue you should resolve

<issue_title>[go-fan] Go Module Review: gojq</issue_title>
<issue_description># 🐹 Go Fan Report: gojq

Module Overview

gojq is a pure Go implementation of jq, the powerful JSON query and transformation language. It provides both a command-line tool and a Go library for parsing and executing jq queries, enabling JSON schema inference and transformation without external dependencies.

Current Version: v0.12.18 (latest, released Dec 1, 2025)
License: MIT
Stars: 3,666+
Maintenance: Active (last push 12 days ago)

Current Usage in gh-aw-mcpg

The project uses gojq in the jqschema middleware (internal/middleware/jqschema.go) to transform JSON responses into type schemas.

  • Files: 3 files (jqschema.go, jqschema_test.go, jqschema_integration_test.go)
  • Import Count: 1 import
  • Key APIs Used:
    • gojq.Parse(query) - Parse jq query strings
    • query.Run(input) - Execute queries against JSON data
    • Iterator pattern with iter.Next()

Current Pattern:

query, err := gojq.Parse(jqSchemaFilter)
iter := query.Run(jsonData)
v, ok := iter.Next()

This parses the same jq query on every request which is a significant performance bottleneck.

Research Findings

Recent Updates

v0.12.18 (Dec 1, 2025) - Latest release includes:

  • Performance improvements for long-running queries
  • Thread-safety fix: Stop numeric normalization for concurrent execution
  • Memory allocation optimizations
  • Array index limit increased to 536M
  • New functions: trimstr/1, toboolean/0
  • Improved gojq.NewIter as generic function

Best Practices from Maintainers

The gojq documentation strongly recommends a compile-once pattern for repeated queries:

"You can use gojq.Compile and code.Run to reuse the compiled code against multiple inputs to avoid compilation of the same query."

Key recommendations:

  1. Compile once, run many - Pre-compile queries at startup
  2. Use context - RunWithContext for timeout/cancellation
  3. Type-specific errors - Check for gojq.HaltError, ParseError
  4. Thread safety - v0.12.18 fixes ensure safe concurrent access to compiled code

Improvement Opportunities

🏃 Quick Wins

1. Compile Query Once (CRITICAL - High Impact, Low Effort)

Current Problem: Query is parsed on every request
Impact: 3-10x performance improvement
Effort: 10 minutes
Risk: Very low

Implementation:

var (
    jqSchemaCode *gojq.Code
    jqSchemaCompileErr error
)

func init() {
    query, err := gojq.Parse(jqSchemaFilter)
    if err != nil {
        jqSchemaCompileErr = fmt.Errorf("failed to parse jq schema filter: %w", err)
        return
    }
    jqSchemaCode, jqSchemaCompileErr = gojq.Compile(query)
}

func applyJqSchema(jsonData interface{}) (string, error) {
    if jqSchemaCompileErr != nil {
        return "", jqSchemaCompileErr
    }
    iter := jqSchemaCode.Run(jsonData)  // Reuse compiled code
    // ... rest
}

2. Add Context Support (Medium Impact, Low Effort)

Current Problem: No timeout/cancellation support
Impact: Better resource management, prevents runaway queries
Effort: 5 minutes
Risk: Very low

Implementation:

func applyJqSchema(ctx context.Context, jsonData interface{}) (string, error) {
    if jqSchemaCompileErr != nil {
        return "", jqSchemaCompileErr
    }
    iter := jqSchemaCode.RunWithContext(ctx, jsonData)
    // ... rest
}

3. Improve Error Handling (Low Impact, Low Effort)

Current Problem: Generic error checking
Impact: Better debugging experience
Effort: 15 minutes
Risk: Very low

Implementation:

if err, ok := v.(error); ok {
    if haltErr, ok := err.(*gojq.HaltError); ok && haltErr.Value() == nil {
        break  // Clean halt - no error
    }
    return "", fmt.Errorf("jq schema filter error: %w", err)
}

✨ Feature Opportunities

  1. Custom Functions for Schema Inference

    • Use gojq.WithFunction to add custom schema functions
    • Enable more sophisticated schema analysis
    • Reduce query complexity
  2. Performance Monitoring

    • Add metrics tracking query execution time
    • Alert on slow queries (>100ms)
    • Monitor memory usage patterns
  3. Query Validation at Startup

    • Compile all jq queries during initialization
    • Fail fast if queries are invalid
    • Better error messages at startup vs runtime
  4. Multiple Query Support

    • Pre-compile multiple schema strategies
    • Select query based on response type/size
    • Optimize for common patterns

📐 Best Practice Alignment

Aspect Current Recommended Benefit
Query Compilation Parse on every request Compile once at startup 3-10x performance
Context Support None Use `RunWithContext...

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 5 commits January 19, 2026 16:38
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Update Go module review for gojq Optimize gojq middleware: pre-compile query for 1.8-5.25x speedup Jan 19, 2026
Copilot AI requested a review from lpcox January 19, 2026 16:46
@lpcox lpcox marked this pull request as ready for review January 19, 2026 16:51
@lpcox lpcox merged commit 333a2a9 into main Jan 19, 2026
3 checks passed
@lpcox lpcox deleted the copilot/update-go-module-review-gojq branch January 19, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[go-fan] Go Module Review: gojq

2 participants