feat(api): add filter by key support to list-customers operation#3694
feat(api): add filter by key support to list-customers operation#3694tothandras merged 4 commits intomainfrom
Conversation
📝 WalkthroughWalkthroughAdds a deepObject Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
🧰 Additional context used📓 Path-based instructions (2)**/*.go⚙️ CodeRabbit configuration file
Files:
**/*.tsp⚙️ CodeRabbit configuration file
Files:
🧠 Learnings (1)📚 Learning: 2025-12-12T15:11:45.299ZApplied to files:
🧬 Code graph analysis (1)api/v3/handlers/customers/list.go (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
🔇 Additional comments (6)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
api/spec/src/v3/customers/operations.tsp (1)
33-46: Makefiltercodegen-friendlier (explicit name + named model) and consider basic constraintsDeepObject is a good fit here, but for multi-toolchain stability I’d strongly consider:
- setting an explicit query name (
name: "filter") rather than relying on the property name, and- extracting the anonymous inline object into a named
model(so clients see a stable schema name and generators don’t diverge).Also:
filter.keyis unbounded right now; adding something like a max length (aligned with the customerkeyconstraints) would help avoid “accidental full-table scan with a 10KB substring”. As per coding guidelines, this is worth tightening since it can hit DB paths.api/v3/handlers/customers/list.go (1)
71-84: Simplify the pointer plumbing + guard against empty/blankfilter.keyYou can collapse Lines 71-77 to just:
if params.Filter != nil { filterKey = params.Filter.Key }More importantly: consider treating
filter[key]=(or whitespace) asnil(or a 400), otherwise it’s easy to accidentally trigger an unselective “match everything” query (depending on how the storage layer does partial matching).
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
api/v3/openapi.yamlis excluded by!**/openapi.yaml
📒 Files selected for processing (3)
api/spec/src/v3/customers/operations.tsp(1 hunks)api/v3/api.gen.go(4 hunks)api/v3/handlers/customers/list.go(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
⚙️ CodeRabbit configuration file
**/*.go: In general when reviewing the Golang code make readability and maintainability a priority, even potentially suggest restructuring the code to improve them.Performance should be a priority in critical code paths. Anything related to event ingestion, message processing, database operations (regardless of database) should be vetted for potential performance bottlenecks.
Files:
api/v3/handlers/customers/list.goapi/v3/api.gen.go
**/*.tsp
⚙️ CodeRabbit configuration file
**/*.tsp: Review the TypeSpec code for conformity with TypeSpec best practices. When recommending changes also consider the fact that multiple codegeneration toolchains depend on the TypeSpec code, each of which have their idiosyncrasies and bugs.The declared API should be accurate, in parity with the actual implementation, and easy to understand for the user.
Files:
api/spec/src/v3/customers/operations.tsp
🧠 Learnings (2)
📓 Common learnings
Learnt from: gergely-kurucz-konghq
Repo: openmeterio/openmeter PR: 3690
File: api/v3/handlers/customers/list.go:44-59
Timestamp: 2025-12-12T15:11:45.299Z
Learning: In the v3 customers list endpoint (api/v3/handlers/customers/list.go), multi-sort (comma-separated sort fields) is intentionally not supported yet, even though the API spec documentation mentions it. The handler uses ParseSortBy() which only handles a single sort field.
📚 Learning: 2025-12-12T15:11:45.299Z
Learnt from: gergely-kurucz-konghq
Repo: openmeterio/openmeter PR: 3690
File: api/v3/handlers/customers/list.go:44-59
Timestamp: 2025-12-12T15:11:45.299Z
Learning: In the v3 customers list endpoint (api/v3/handlers/customers/list.go), multi-sort (comma-separated sort fields) is intentionally not supported yet, even though the API spec documentation mentions it. The handler uses ParseSortBy() which only handles a single sort field.
Applied to files:
api/v3/api.gen.go
🧬 Code graph analysis (1)
api/v3/handlers/customers/list.go (4)
openmeter/customer/httpdriver/customer.go (1)
ListCustomersRequest(28-28)app/common/namespace.go (1)
Namespace(13-15)pkg/pagination/page.go (1)
Page(14-17)pkg/sortx/order.go (1)
Order(3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (go)
🔇 Additional comments (4)
api/v3/api.gen.go (4)
482-487: Generated filter model looks fine; please sanity-check deepObject binding behaviorThis is straightforward, but since it relies on oapi-codegen/runtime’s deepObject binding, I’d add/confirm a small test that
?filter[key]=acmeends up inparams.Filter.Key.
537-539:ListCustomersParams.Filterwiring is the right shape; verify tags aren’t needed for your binderGiven
Sortcarries aformtag butFilterdoesn’t, just make sure your current oapi-codegen/runtime version binds deepObject into*ListCustomersParamsFilterreliably without additional struct tags.
802-809: Nice: consistent deepObject binding + good error mappingBinding + surfacing
InvalidParamFormatError{ParamName: "filter" ...}is exactly what I’d want here.
1062-1147: Generated swaggerSpec blobAssuming this file is fully generated in-repo, I’m not reviewing this chunk beyond “looks like a regen artifact”.
a16cc2f to
d27e468
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
api/spec/src/v3/customers/operations.tsp (1)
16-26: Nice, clean filter shape — but please add a concrete usage example.Since this is a deepObject param, an explicit example in the docblock helps a ton (e.g.
filter[key]=my-db-id) and reduces “how do I call this?” confusion. Based on past review comments, please add an inline example near the filter docs.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
api/v3/openapi.yamlis excluded by!**/openapi.yaml
📒 Files selected for processing (3)
api/spec/src/v3/customers/operations.tsp(2 hunks)api/v3/api.gen.go(4 hunks)api/v3/handlers/customers/list.go(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
⚙️ CodeRabbit configuration file
**/*.go: In general when reviewing the Golang code make readability and maintainability a priority, even potentially suggest restructuring the code to improve them.Performance should be a priority in critical code paths. Anything related to event ingestion, message processing, database operations (regardless of database) should be vetted for potential performance bottlenecks.
Files:
api/v3/handlers/customers/list.goapi/v3/api.gen.go
**/*.tsp
⚙️ CodeRabbit configuration file
**/*.tsp: Review the TypeSpec code for conformity with TypeSpec best practices. When recommending changes also consider the fact that multiple codegeneration toolchains depend on the TypeSpec code, each of which have their idiosyncrasies and bugs.The declared API should be accurate, in parity with the actual implementation, and easy to understand for the user.
Files:
api/spec/src/v3/customers/operations.tsp
🧠 Learnings (1)
📚 Learning: 2025-12-12T15:11:45.299Z
Learnt from: gergely-kurucz-konghq
Repo: openmeterio/openmeter PR: 3690
File: api/v3/handlers/customers/list.go:44-59
Timestamp: 2025-12-12T15:11:45.299Z
Learning: In the v3 customers list endpoint (api/v3/handlers/customers/list.go), multi-sort (comma-separated sort fields) is intentionally not supported yet, even though the API spec documentation mentions it. The handler uses ParseSortBy() which only handles a single sort field.
Applied to files:
api/v3/api.gen.go
🧬 Code graph analysis (1)
api/v3/handlers/customers/list.go (4)
openmeter/customer/httpdriver/customer.go (1)
ListCustomersRequest(28-28)api/v3/apierrors/errors_ctors.go (1)
NewBadRequestError(198-209)api/v3/api.gen.go (1)
InvalidParameters(413-413)api/v3/apierrors/errors.go (2)
InvalidParameter(107-134)InvalidParamSourceQuery(60-60)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Artifacts / Container image
- GitHub Check: Code Generators
- GitHub Check: Artifacts / Benthos Collector Container image
- GitHub Check: Lint
- GitHub Check: Test
- GitHub Check: Migration Checks
- GitHub Check: Build
- GitHub Check: Repository Scan
- GitHub Check: Analyze (go)
🔇 Additional comments (5)
api/v3/api.gen.go (3)
428-433: Generated types look consistent with the TypeSpec additions.
ListCustomersParamsFilterandListCustomersParams.Filtermatch the intended shape and keep the filter optional — nice and non-breaking.Also applies to: 659-662
1333-1433: swaggerSpec blob update is expected for generated code.
970-977: The deepObject binding and error handling look correct for oapi-codegen v2.5.0. The code properly handles the OpenAPI deepObject semantics (paramName[prop]=value, e.g.,?filter[key]=abc), and error handling is consistent across all parameters—InvalidParamFormatErrorwill be raised for malformed inputs.That said, if this parameter is critical to your API, quick end-to-end testing of those query shapes would be a good sanity check just to be sure the OpenAPI spec and runtime behavior align in your actual deployment.
api/spec/src/v3/customers/operations.tsp (1)
48-52: deepObject style with explode: true is spec-correct, but codegen can be finicky.The TypeSpec setup here follows the OpenAPI spec and will produce the right
?filter[key]=valueencoding. That said, deepObject support varies across codegen toolchains—some generators have spotty or inconsistent implementations. Worth running a quick end-to-end test with the specific generators/versions your consumers use to confirm the query params encode and decode as expected. If you hit issues, consider falling back to explicit separate query parameters or a single JSON-encoded value as a workaround.api/v3/handlers/customers/list.go (1)
71-88: Case-insensitive partial matching is properly enforced downstream. The handler validates key length while the adapter layer appliesKeyContainsFold, which generates case-insensitive partial match queries (ILIKE in PostgreSQL). This separation of concerns is correct—input validation belongs in the handler, and filtering logic belongs in the adapter/database layer.
Request validator middleware will take care of validating against the corresponding operation from the openapi schema.
6e6c73b to
788bf53
Compare
Summary by CodeRabbit
New Features
Bug Fixes / Validation
✏️ Tip: You can customize this high-level summary in your review settings.