Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(api): add filter by key support to list-customers operation#3694

Merged
tothandras merged 4 commits intomainfrom
feat/api-v3-customers-filter
Dec 15, 2025
Merged

feat(api): add filter by key support to list-customers operation#3694
tothandras merged 4 commits intomainfrom
feat/api-v3-customers-filter

Conversation

@gergely-kurucz-konghq
Copy link
Contributor

@gergely-kurucz-konghq gergely-kurucz-konghq commented Dec 12, 2025

Summary by CodeRabbit

  • New Features

    • Customer list API now supports an optional key-based filter (case-insensitive partial matches) via query (e.g., filter[key]=...).
    • List endpoint accepts standard pagination and sorting query parameters to control page size/number and result order.
  • Bug Fixes / Validation

    • Added validation for filter key length (1–256); invalid values return a Bad Request/Invalid Parameter error.

✏️ Tip: You can customize this high-level summary in your review settings.

@gergely-kurucz-konghq gergely-kurucz-konghq requested a review from a team as a code owner December 12, 2025 19:09
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

📝 Walkthrough

Walkthrough

Adds a deepObject filter query parameter with a nested key field to the customers list endpoint, exposes a new ListCustomersParamsFilter model and Filter field on ListCustomersParams, and threads params.Filter.Key through the generated API types into the ListCustomers handler as an optional Key for server-side filtering.

Changes

Cohort / File(s) Summary
API spec
api/spec/src/v3/customers/operations.tsp
Added public model ListCustomersParamsFilter with key?: Shared.ExternalResourceKey and added filter?: ListCustomersParamsFilter to ListCustomersParams using style: deepObject, explode: true.
Generated API types & wiring
api/v3/api.gen.go
Added ListCustomersParamsFilter (Key *ExternalResourceKey), added PagePaginationQuery, exposed several error-type aliases, extended ListCustomersParams with Filter *ListCustomersParamsFilter, and updated server binding to parse the filter deepObject query parameter and surface invalid-param-format errors; updated embedded swagger payload.
Handler implementation
api/v3/handlers/customers/list.go
Reads params.Filter.Key when present and forwards it as Key on the ListCustomersRequest passed to the service layer.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Check deepObject binding and InvalidParamFormatError behavior in api/v3/api.gen.go.
  • Verify Filter.Key type (ExternalResourceKey) matches downstream filter/predicate expectations.
  • Confirm handler propagation preserves nullable vs empty-string semantics.

Possibly related PRs

Suggested labels

area/api, release-note/feature

Suggested reviewers

  • turip

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(api): add filter by key support to list-customers operation' accurately reflects the main changes: adding a filter-by-key feature to the list-customers API endpoint.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/api-v3-customers-filter

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e6c73b and 788bf53.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is 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.go
  • api/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 (1)
openmeter/customer/httpdriver/customer.go (1)
  • ListCustomersRequest (28-28)
⏰ 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)
  • GitHub Check: Artifacts / Container image
  • GitHub Check: Migration Checks
  • GitHub Check: Code Generators
  • GitHub Check: Test
  • GitHub Check: Lint
  • GitHub Check: Build
  • GitHub Check: Repository Scan
  • GitHub Check: Analyze (go)
🔇 Additional comments (6)
api/v3/handlers/customers/list.go (1)

71-82: LGTM! Clean implementation of filter parameter extraction.

The nil check before accessing params.Filter.Key is good, and the straightforward passthrough to the request keeps the handler layer simple.

api/spec/src/v3/customers/operations.tsp (2)

48-54: Nice documentation with the usage example! 🎉

The deepObject query parameter style is the right choice here, and the example filter[key]=my-db-id makes it super clear how to use this filter.


16-26: Good catch—the implementation matches the documentation.

The service layer does implement case-insensitive partial matching for the key filter. Line 53 of openmeter/customer/adapter/customer.go uses customerdb.KeyContainsFold(), which provides exactly the case-insensitive partial match behavior documented in the TypeSpec model.

api/v3/api.gen.go (3)

463-468: Generated type looks correct.

The type definition matches the TypeSpec, with the optional Key field properly represented as a pointer with omitempty.


694-698: Generated filter field matches the spec nicely.

The field definition and documentation are correctly generated from the TypeSpec.


1016-1022: Parameter binding correctly implements the deepObject style.

The generated binding code properly uses deepObject with explode: true, matching the TypeSpec definition.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gergely-kurucz-konghq gergely-kurucz-konghq added the release-note/misc Miscellaneous changes label Dec 12, 2025
tothandras
tothandras previously approved these changes Dec 12, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
api/spec/src/v3/customers/operations.tsp (1)

33-46: Make filter codegen-friendlier (explicit name + named model) and consider basic constraints

DeepObject 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.key is unbounded right now; adding something like a max length (aligned with the customer key constraints) 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/blank filter.key

You can collapse Lines 71-77 to just:

  • if params.Filter != nil { filterKey = params.Filter.Key }

More importantly: consider treating filter[key]= (or whitespace) as nil (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

📥 Commits

Reviewing files that changed from the base of the PR and between cbb1e28 and a16cc2f.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is 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.go
  • api/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 behavior

This is straightforward, but since it relies on oapi-codegen/runtime’s deepObject binding, I’d add/confirm a small test that ?filter[key]=acme ends up in params.Filter.Key.


537-539: ListCustomersParams.Filter wiring is the right shape; verify tags aren’t needed for your binder

Given Sort carries a form tag but Filter doesn’t, just make sure your current oapi-codegen/runtime version binds deepObject into *ListCustomersParamsFilter reliably without additional struct tags.


802-809: Nice: consistent deepObject binding + good error mapping

Binding + surfacing InvalidParamFormatError{ParamName: "filter" ...} is exactly what I’d want here.


1062-1147: Generated swaggerSpec blob

Assuming this file is fully generated in-repo, I’m not reviewing this chunk beyond “looks like a regen artifact”.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between d27e468 and 8726297.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is 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.go
  • api/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.

ListCustomersParamsFilter and ListCustomersParams.Filter match 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—InvalidParamFormatError will 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]=value encoding. 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 applies KeyContainsFold, 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.

tothandras
tothandras previously approved these changes Dec 13, 2025
@gergely-kurucz-konghq gergely-kurucz-konghq force-pushed the feat/api-v3-customers-filter branch from 6e6c73b to 788bf53 Compare December 14, 2025 22:51
@gergely-kurucz-konghq gergely-kurucz-konghq changed the title feat(api): add filter by key support to list-customers operation and … feat(api): add filter by key support to list-customers operation Dec 14, 2025
@tothandras tothandras merged commit 6ed4b74 into main Dec 15, 2025
25 checks passed
@tothandras tothandras deleted the feat/api-v3-customers-filter branch December 15, 2025 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/misc Miscellaneous changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants