Add timeout enforcement and comprehensive tests for gojq middleware#961
Add timeout enforcement and comprehensive tests for gojq middleware#961
Conversation
Implements Priority 2 improvements from Go Fan review: - Added automatic 5-second timeout for jq queries - Enhanced documentation referencing gojq v0.12.18 features - Added comprehensive unit tests for timeout behavior - Fixed unused require declarations in sys_test.go Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This pull request implements Priority 2 recommendations from the Go Fan module review for the gojq middleware, adding robust timeout protection and comprehensive test coverage. The changes enhance the reliability of JSON query processing by preventing hangs from malformed queries or excessively large payloads.
Changes:
- Added 5-second default timeout enforcement for jq query execution to prevent hangs
- Enhanced documentation referencing gojq v0.12.18 features (536M element array limit, improved concurrency, better error messages)
- Added 9 comprehensive timeout-related tests covering default timeout application, deadline preservation, large arrays, nested structures, compilation errors, and context cancellation
- Fixed 4 unused require declarations in sys_test.go through formatting cleanup
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| internal/middleware/jqschema.go | Added DefaultJqTimeout constant (5s), enhanced applyJqSchema() to automatically enforce timeout when context lacks deadline, improved error handling for timeouts/cancellation, updated documentation with gojq v0.12.18 features |
| internal/middleware/jqschema_test.go | Added TestApplyJqSchema_TimeoutBehavior and TestApplyJqSchema_ContextTimeout test functions with 9 comprehensive test cases covering timeout behavior, large data processing, nested structures, and error scenarios |
| internal/sys/sys_test.go | Code formatting improvements (indentation standardization) and removal of 4 unused require declarations in test functions that only use assert |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Add timeout enforcement and comprehensive tests for gojq middleware
|
Implements Priority 2 recommendations from the Go Fan module review for the gojq middleware, adding timeout protection and comprehensive test coverage.
Changes
Timeout Protection
DefaultJqTimeoutconstant (5 seconds) to prevent query hangsapplyJqSchema()to automatically enforce timeout when context lacks a deadlineDocumentation
init()function documentation explaining fail-fast behaviorapplyJqSchema()Test Coverage
Code Quality
requiredeclarations ininternal/sys/sys_test.goExample
All middleware tests pass (30+ test cases). The implementation leverages pre-existing query compilation caching (10-100x speedup) while adding robust timeout protection.
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
example.com/tmp/go-build1592018226/b275/launcher.test /tmp/go-build1592018226/b275/launcher.test -test.testlogfile=/tmp/go-build1592018226/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a 64/src/math/exp_net/http/httptrace ache/go/1.25.7/x-lang=go1.25 get go-sdk/internal/-v ache/Python/3.12-buildid ache/go/1.25.7/xTaEENvXcKh3a5hEPOj9o/TaEENvXcKh3a5hEPOj9o abis�� 64/src/runtime/cgo1.25.7 HEAD x_amd64/vet --global fips140/alias(dns block)/tmp/go-build3921665002/b275/launcher.test /tmp/go-build3921665002/b275/launcher.test -test.testlogfile=/tmp/go-build3921665002/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true /opt/hostedtoolcache/go/1.25.7/x64/src/net -I 2018226/b260/config.test --gdwarf-5 --64 -o 2018226/b260/conHEAD e=/t�� t0 m0s docker-compose(dns block)/tmp/go-build1222286590/b275/launcher.test /tmp/go-build1222286590/b275/launcher.test -test.testlogfile=/tmp/go-build1222286590/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true MJ37E2qau -tests ker/docker-init go HEAD 64/pkg/tool/linux_amd64/compile ortcfg -d aw-mcpg/internal/testutil/mcptest/config.go aw-mcpg/internal/testutil/mcptest/driver.go /usr/local/sbin/bash g_.a go x_amd64/vet bash(dns block)invalid-host-that-does-not-exist-12345.com/tmp/go-build1592018226/b260/config.test /tmp/go-build1592018226/b260/config.test -test.testlogfile=/tmp/go-build1592018226/b260/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true sonrpc2/conn.go sonrpc2/frame.go .12/x64/bin/as ; s#git --global bin/git 64/pkg/include ortc�� 64/src/runtime/cgo 64/src/crypto/internal/fips140de--gdwarf2 inux.go esnew.go ocknew.go nix_cgo.go nix_cgo_res.go(dns block)/tmp/go-build1856060892/b260/config.test /tmp/go-build1856060892/b260/config.test -test.testlogfile=/tmp/go-build1856060892/b260/testlog.txt -test.paniconexit0 -test.timeout=10m0s rev-�� --abbrev-ref HEAD cal/bin/git tion_pool.go er.go 64/pkg/tool/linux_amd64/vet base64 -d(dns block)nonexistent.local/tmp/go-build1592018226/b275/launcher.test /tmp/go-build1592018226/b275/launcher.test -test.testlogfile=/tmp/go-build1592018226/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a 64/src/math/exp_net/http/httptrace ache/go/1.25.7/x-lang=go1.25 get go-sdk/internal/-v ache/Python/3.12-buildid ache/go/1.25.7/xTaEENvXcKh3a5hEPOj9o/TaEENvXcKh3a5hEPOj9o abis�� 64/src/runtime/cgo1.25.7 HEAD x_amd64/vet --global fips140/alias(dns block)/tmp/go-build3921665002/b275/launcher.test /tmp/go-build3921665002/b275/launcher.test -test.testlogfile=/tmp/go-build3921665002/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true /opt/hostedtoolcache/go/1.25.7/x64/src/net -I 2018226/b260/config.test --gdwarf-5 --64 -o 2018226/b260/conHEAD e=/t�� t0 m0s docker-compose(dns block)/tmp/go-build1222286590/b275/launcher.test /tmp/go-build1222286590/b275/launcher.test -test.testlogfile=/tmp/go-build1222286590/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true MJ37E2qau -tests ker/docker-init go HEAD 64/pkg/tool/linux_amd64/compile ortcfg -d aw-mcpg/internal/testutil/mcptest/config.go aw-mcpg/internal/testutil/mcptest/driver.go /usr/local/sbin/bash g_.a go x_amd64/vet bash(dns block)slow.example.com/tmp/go-build1592018226/b275/launcher.test /tmp/go-build1592018226/b275/launcher.test -test.testlogfile=/tmp/go-build1592018226/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a 64/src/math/exp_net/http/httptrace ache/go/1.25.7/x-lang=go1.25 get go-sdk/internal/-v ache/Python/3.12-buildid ache/go/1.25.7/xTaEENvXcKh3a5hEPOj9o/TaEENvXcKh3a5hEPOj9o abis�� 64/src/runtime/cgo1.25.7 HEAD x_amd64/vet --global fips140/alias(dns block)/tmp/go-build3921665002/b275/launcher.test /tmp/go-build3921665002/b275/launcher.test -test.testlogfile=/tmp/go-build3921665002/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true /opt/hostedtoolcache/go/1.25.7/x64/src/net -I 2018226/b260/config.test --gdwarf-5 --64 -o 2018226/b260/conHEAD e=/t�� t0 m0s docker-compose(dns block)/tmp/go-build1222286590/b275/launcher.test /tmp/go-build1222286590/b275/launcher.test -test.testlogfile=/tmp/go-build1222286590/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true MJ37E2qau -tests ker/docker-init go HEAD 64/pkg/tool/linux_amd64/compile ortcfg -d aw-mcpg/internal/testutil/mcptest/config.go aw-mcpg/internal/testutil/mcptest/driver.go /usr/local/sbin/bash g_.a go x_amd64/vet bash(dns block)this-host-does-not-exist-12345.com/tmp/go-build1592018226/b284/mcp.test /tmp/go-build1592018226/b284/mcp.test -test.testlogfile=/tmp/go-build1592018226/b284/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/runtime/cgo Vl8znsXtV x_amd64/cgo rt-size '1280, 7/opt/hostedtoolcache/go/1.25.7/x64/pkg/tool/linux_amd64/compile fips140/check cal/bin/npx x_amd64/cgo ortc�� 0938582/b193/_pk-p mon/httpcommon.ggithub.com/github/gh-aw-mcpg/internal/logger/sanitize x_amd64/vet unset --global ache/Python/3.12--version x_amd64/vet(dns block)/tmp/go-build1856060892/b284/mcp.test /tmp/go-build1856060892/b284/mcp.test -test.testlogfile=/tmp/go-build1856060892/b284/testlog.txt -test.paniconexit0 -test.timeout=10m0s rev-�� --abbrev-ref HEAD ache/go/1.25.7/x64/pkg/tool/linux_amd64/compile /opt/hostedtoolc/opt/hostedtoolcache/go/1.25.7/x64/pkg/tool/linux_amd64/link 0938582/b194/ ache/go/1.25.7/x/tmp/go-build1856060892/b260/config.test ache/go/1.25.7/x-importcfg de 1665002/b293/_pk-s HEAD 1665002/b293=> /guard/context.ggrep /guard/guard.go 64/pkg/tool/linu(create|run) git(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
This section details on the original issue you should resolve
<issue_title>[go-fan] Go Module Review: gojq - JSON Query Processing</issue_title>
<issue_description># 🐹 Go Fan Report: github.com/itchyny/gojq
Module Overview
gojq is a pure Go implementation of jq - the powerful JSON query language and processor. It provides both a CLI tool and a Go library for programmatically processing JSON data with jq queries. This module is critical for the MCP Gateway's middleware layer, enabling sophisticated JSON transformations and schema generation on MCP tool responses.
Current Usage in gh-aw-mcpg
Based on GitHub code search, gojq is used in 2 files:
Files
internal/middleware/jqschema.go- Main implementation for jq-based schema generationinternal/middleware/jqschema_bench_test.go- Performance benchmarksKey APIs Used
The middleware likely leverages:
gojq.Parse()- Parse jq query stringsgojq.Compile()- Compile queries into executable codeCode.Run()- Execute compiled queries on JSON dataContext
The middleware uses gojq for:
Research Findings
Recent Updates (v0.12.18 - December 2025)
🎉 Major improvements in latest release:
New Functions
trimstr/1- Efficient prefix/suffix removal (better than string slicing)toboolean/0- Clean type conversionPerformance & Scale
1 + 2 as $x | -$x)Bug Fixes
last/1to be included inbuiltins/0--indent 0to preserve newlinesVery Recent Activity (January 2026)
Best Practices from gojq Documentation
Run()which returns an iterator for memory-efficient processinggojq.WithFunction()Improvement Opportunities
🏃 Quick Wins (High Impact, Low Effort)
1. Leverage New v0.12.18 Functions
Impact: Medium | Effort: Low
trimstr/1instead of manual string slicing for prefix/suffix removaltoboolean/0instead of custom type conversion logicExample:
2. Utilize Increased Array Index Limit
Impact: High | Effort: Low
v0.12.18 dramatically increased the array index limit to 536,870,912 elements (2^29):
3. Improve Error Messages
Impact: Medium | Effort: Low
Recent fixes improved type error messages for
split()andmatch():✨ Feature Opportunities (High Impact, Medium/High Effort)
1. Query Compilation Caching 🔥
Impact: High | Effort: Medium
Problem: If jq queries are recompiled on every request, it wastes significant CPU.
Solution: Implement a compilation cache using
sync.Map: