From 3bf0c389e7a5c51b7b1c90140ba501afc6cdeaa7 Mon Sep 17 00:00:00 2001 From: Andras Toth <4157749+tothandras@users.noreply.github.com> Date: Wed, 10 Jun 2026 00:53:38 +0200 Subject: [PATCH 1/2] feat(api): add event subject list endpoint --- .../packages/aip-client-javascript/README.md | 9 +- .../aip-client-javascript/src/funcs/events.ts | 18 + .../aip-client-javascript/src/index.ts | 3 + .../src/models/operations/events.ts | 11 + .../src/models/schemas.ts | 52 +- .../aip-client-javascript/src/models/types.ts | 33 + .../aip-client-javascript/src/sdk/events.ts | 15 +- api/spec/packages/aip/src/events/index.tsp | 1 + .../packages/aip/src/events/operations.tsp | 41 + api/spec/packages/aip/src/events/subject.tsp | 20 + api/spec/packages/aip/src/konnect.tsp | 4 + api/spec/packages/aip/src/openmeter.tsp | 4 + api/v3/api.gen.go | 1414 +++++++++-------- api/v3/handlers/events/handler.go | 1 + api/v3/handlers/events/list_subjects.go | 159 ++ api/v3/openapi.yaml | 94 ++ api/v3/server/routes.go | 4 + app/common/streaming.go | 23 +- app/config/aggregation.go | 8 + e2e/events_subjects_v3_test.go | 108 ++ e2e/v3helpers_test.go | 18 + openmeter/meterevent/adapter/subject.go | 136 ++ openmeter/meterevent/adapter/subject_test.go | 223 +++ openmeter/meterevent/service.go | 1 + openmeter/meterevent/subject.go | 67 + openmeter/meterevent/subject_test.go | 103 ++ openmeter/server/server_test.go | 4 + openmeter/streaming/clickhouse/connector.go | 65 + .../streaming/clickhouse/subject_query.go | 63 + .../clickhouse/subject_query_test.go | 74 + openmeter/streaming/connector.go | 43 + openmeter/streaming/retry/retry.go | 6 + openmeter/streaming/testutils/streaming.go | 4 + 33 files changed, 2140 insertions(+), 689 deletions(-) create mode 100644 api/spec/packages/aip/src/events/subject.tsp create mode 100644 api/v3/handlers/events/list_subjects.go create mode 100644 e2e/events_subjects_v3_test.go create mode 100644 openmeter/meterevent/adapter/subject.go create mode 100644 openmeter/meterevent/adapter/subject_test.go create mode 100644 openmeter/meterevent/subject.go create mode 100644 openmeter/meterevent/subject_test.go diff --git a/api/spec/packages/aip-client-javascript/README.md b/api/spec/packages/aip-client-javascript/README.md index 2664890311..333b7aafc9 100644 --- a/api/spec/packages/aip-client-javascript/README.md +++ b/api/spec/packages/aip-client-javascript/README.md @@ -113,10 +113,11 @@ The full call path, HTTP route, and a short description are listed below. ### Events -| Method | HTTP | Description | -| ---------------------- | ------------------------ | ---------------------------------------------------------------------------- | -| `client.events.list` | `GET /openmeter/events` | List ingested events. | -| `client.events.ingest` | `POST /openmeter/events` | Ingests an event or batch of events following the CloudEvents specification. | +| Method | HTTP | Description | +| ---------------------------- | -------------------------------- | ------------------------------------------------------------------------------------- | +| `client.events.list` | `GET /openmeter/events` | List ingested events. | +| `client.events.ingest` | `POST /openmeter/events` | Ingests an event or batch of events following the CloudEvents specification. | +| `client.events.listSubjects` | `GET /openmeter/events/subjects` | List the subjects of the ingested events. Subjects are ordered by key alphabetically. | ### Meters diff --git a/api/spec/packages/aip-client-javascript/src/funcs/events.ts b/api/spec/packages/aip-client-javascript/src/funcs/events.ts index 3ce55bd39e..df73f7b59d 100644 --- a/api/spec/packages/aip-client-javascript/src/funcs/events.ts +++ b/api/spec/packages/aip-client-javascript/src/funcs/events.ts @@ -7,6 +7,8 @@ import type { ListMeteringEventsResponse, IngestMeteringEventsRequest, IngestMeteringEventsResponse, + ListEventSubjectsRequest, + ListEventSubjectsResponse, } from '../models/operations/events.js' export function listMeteringEvents( @@ -35,3 +37,19 @@ export function ingestMeteringEvents( await http(client).post('openmeter/events', { ...options, json: req }) }) } + +export function listEventSubjects( + client: Client, + req: ListEventSubjectsRequest = {}, + options?: RequestOptions, +): Promise> { + const searchParams = toURLSearchParams({ + page: req.page, + filter: req.filter, + }) + return request(() => + http(client) + .get('openmeter/events/subjects', { ...options, searchParams }) + .json(), + ) +} diff --git a/api/spec/packages/aip-client-javascript/src/index.ts b/api/spec/packages/aip-client-javascript/src/index.ts index 0f9adb9b2d..e4547347b5 100644 --- a/api/spec/packages/aip-client-javascript/src/index.ts +++ b/api/spec/packages/aip-client-javascript/src/index.ts @@ -55,6 +55,7 @@ export type { IngestedEventValidationError, CursorMetaPage, BaseError, + EventSubject, PageMeta, QueryFilterString, AppStripeCheckoutSessionCustomTextParams, @@ -140,6 +141,7 @@ export type { Internal, NotImplemented, NotAvailable, + ListSubjectsParamsFilter, CreateCreditGrantFilters, CreditGrantFilters, UpsertPlanAddonRequest, @@ -212,6 +214,7 @@ export type { IngestedEvent, MeterQueryResult, FeatureCostQueryResult, + SubjectPaginatedResponse, MeterPagePaginatedResponse, CostBasisPagePaginatedResponse, MeterQueryFilters, diff --git a/api/spec/packages/aip-client-javascript/src/models/operations/events.ts b/api/spec/packages/aip-client-javascript/src/models/operations/events.ts index c61f3ee344..b9ffe766f9 100644 --- a/api/spec/packages/aip-client-javascript/src/models/operations/events.ts +++ b/api/spec/packages/aip-client-javascript/src/models/operations/events.ts @@ -5,7 +5,9 @@ import type { EventInput, IngestedEventPaginatedResponse, ListEventsParamsFilter, + ListSubjectsParamsFilter, SortQueryInput, + SubjectPaginatedResponse, } from '../types.js' export interface ListMeteringEventsQuery { @@ -21,3 +23,12 @@ export type ListMeteringEventsResponse = IngestedEventPaginatedResponse export type IngestMeteringEventsRequest = EventInput | EventInput[] export type IngestMeteringEventsResponse = void + +export interface ListEventSubjectsQuery { + page?: CursorPaginationQueryPage + /** Filter subjects returned in the response. To filter subjects by key add the following query param: filter[key][contains]=customer */ + filter?: ListSubjectsParamsFilter +} + +export type ListEventSubjectsRequest = ListEventSubjectsQuery +export type ListEventSubjectsResponse = SubjectPaginatedResponse diff --git a/api/spec/packages/aip-client-javascript/src/models/schemas.ts b/api/spec/packages/aip-client-javascript/src/models/schemas.ts index 88c5cb933c..3855d1a019 100644 --- a/api/spec/packages/aip-client-javascript/src/models/schemas.ts +++ b/api/spec/packages/aip-client-javascript/src/models/schemas.ts @@ -253,6 +253,23 @@ export const baseError = z ) .describe('Standard error response.') +export const booleanFieldFilter = z + .union([ + z.boolean(), + z.object({ + eq: z + .boolean() + .describe('Value strictly equals the given boolean value.'), + }), + ]) + .describe('Filter by a boolean value (true/false).') + +export const eventSubject = z + .object({ + key: z.string().min(1).describe('The key of the subject.'), + }) + .describe('Subject of an event.') + export const resourceKey = z .string() .min(1) @@ -1045,17 +1062,6 @@ export const publicLabels = z 'Public labels store information about an entity that can be used for filtering a list of objects.', ) -export const booleanFieldFilter = z - .union([ - z.boolean(), - z.object({ - eq: z - .boolean() - .describe('Value strictly equals the given boolean value.'), - }), - ]) - .describe('Filter by a boolean value (true/false).') - export const numericFieldFilter = z .union([ z.number(), @@ -1927,6 +1933,13 @@ export const notImplemented = baseError.describe('Not Implemented.') export const notAvailable = baseError.describe('Not Available.') +export const listSubjectsParamsFilter = z + .object({ + key: stringFieldFilter.optional(), + attributed: booleanFieldFilter.optional(), + }) + .describe('Filter options for listing subjects.') + export const createCreditGrantFilters = z .object({ features: z @@ -3152,6 +3165,13 @@ export const featureCostQueryResult = z }) .describe('Result of a feature cost query.') +export const subjectPaginatedResponse = z + .object({ + data: z.array(eventSubject), + meta: cursorMeta, + }) + .describe('Cursor paginated response.') + export const invalidParameter = z .union([ invalidParameterStandard, @@ -4624,6 +4644,16 @@ export const listMeteringEventsResponse = z.object({ export const ingestMeteringEventsBody = event +export const listEventSubjectsQueryParams = z.object({ + page: cursorPaginationQueryPage.optional(), + filter: listSubjectsParamsFilter.optional(), +}) + +export const listEventSubjectsResponse = z.object({ + data: z.array(eventSubject), + meta: cursorMeta, +}) + export const createMeterBody = createMeterRequest export const createMeterResponse = meter diff --git a/api/spec/packages/aip-client-javascript/src/models/types.ts b/api/spec/packages/aip-client-javascript/src/models/types.ts index 9068a54653..6ff868eec9 100644 --- a/api/spec/packages/aip-client-javascript/src/models/types.ts +++ b/api/spec/packages/aip-client-javascript/src/models/types.ts @@ -58,6 +58,12 @@ export interface BaseError { [key: string]: unknown } +/** Subject of an event. */ +export interface EventSubject { + /** The key of the subject. */ + key: string +} + /** Pagination information. */ export interface PageMeta { /** Page number. */ @@ -938,6 +944,27 @@ export interface NotImplemented extends BaseError {} /** Not Available. */ export interface NotAvailable extends BaseError {} +/** Filter options for listing subjects. */ +export interface ListSubjectsParamsFilter { + /** Filter subjects by key. */ + key?: + | string + | { + eq?: string + neq?: string + contains?: string + ocontains?: string[] + oeq?: string[] + gt?: string + gte?: string + lt?: string + lte?: string + exists?: boolean + } + /** Filter subjects by whether they are attributed to a customer. */ + attributed?: boolean | { eq: boolean } +} + /** Filters for the credit grant. */ export interface CreateCreditGrantFilters { /** Limit the credit grant to specific features. If no features are specified, the credit grant can be used for any feature. */ @@ -2089,6 +2116,12 @@ export interface FeatureCostQueryResult { data: FeatureCostQueryRow[] } +/** Cursor paginated response. */ +export interface SubjectPaginatedResponse { + data: EventSubject[] + meta: CursorMeta +} + /** Page paginated response. */ export interface MeterPagePaginatedResponse { data: Meter[] diff --git a/api/spec/packages/aip-client-javascript/src/sdk/events.ts b/api/spec/packages/aip-client-javascript/src/sdk/events.ts index 206454f2a1..eff3faa16a 100644 --- a/api/spec/packages/aip-client-javascript/src/sdk/events.ts +++ b/api/spec/packages/aip-client-javascript/src/sdk/events.ts @@ -1,11 +1,17 @@ import { type Client } from '../core.js' import { unwrap, type RequestOptions } from '../lib/types.js' -import { listMeteringEvents, ingestMeteringEvents } from '../funcs/events.js' +import { + listMeteringEvents, + ingestMeteringEvents, + listEventSubjects, +} from '../funcs/events.js' import type { ListMeteringEventsRequest, ListMeteringEventsResponse, IngestMeteringEventsRequest, IngestMeteringEventsResponse, + ListEventSubjectsRequest, + ListEventSubjectsResponse, } from '../models/operations/events.js' export class Events { @@ -24,4 +30,11 @@ export class Events { ): Promise { return unwrap(await ingestMeteringEvents(this._client, request, options)) } + + async listSubjects( + request?: ListEventSubjectsRequest, + options?: RequestOptions, + ): Promise { + return unwrap(await listEventSubjects(this._client, request, options)) + } } diff --git a/api/spec/packages/aip/src/events/index.tsp b/api/spec/packages/aip/src/events/index.tsp index bfbcb1c554..ab6d64258d 100644 --- a/api/spec/packages/aip/src/events/index.tsp +++ b/api/spec/packages/aip/src/events/index.tsp @@ -1,2 +1,3 @@ import "./event.tsp"; +import "./subject.tsp"; import "./operations.tsp"; diff --git a/api/spec/packages/aip/src/events/operations.tsp b/api/spec/packages/aip/src/events/operations.tsp index 834372b846..0c89e3935d 100644 --- a/api/spec/packages/aip/src/events/operations.tsp +++ b/api/spec/packages/aip/src/events/operations.tsp @@ -7,6 +7,7 @@ import "../common/pagination.tsp"; import "../common/parameters.tsp"; import "../shared/index.tsp"; import "./event.tsp"; +import "./subject.tsp"; using TypeSpec.Http; using TypeSpec.OpenAPI; @@ -132,3 +133,43 @@ interface EventsOperations { @body body: MeteringEvent | MeteringEvent[], ): IngestEventsResponse | Common.ErrorResponses; } + +/** + * Filter options for listing subjects. + */ +@friendlyName("ListSubjectsParamsFilter") +model ListSubjectsParamsFilter { + /** + * Filter subjects by key. + */ + key?: Common.StringFieldFilter; + + /** + * Filter subjects by whether they are attributed to a customer. + */ + attributed?: Common.BooleanFieldFilter; +} + +interface EventsSubjectsOperations { + /** + * List the subjects of the ingested events. Subjects are ordered by key + * alphabetically. + */ + @extension(Shared.UnstableExtension, true) + @extension(Shared.InternalExtension, true) + @get + @operationId("list-event-subjects") + @summary("List event subjects") + list( + ...Common.CursorPaginationQuery, + + /** + * Filter subjects returned in the response. + * + * To filter subjects by key add the following query param: + * filter[key][contains]=customer + */ + @query(#{ style: "deepObject", explode: true }) + filter?: ListSubjectsParamsFilter, + ): Shared.CursorPaginatedResponse | Common.ErrorResponses; +} diff --git a/api/spec/packages/aip/src/events/subject.tsp b/api/spec/packages/aip/src/events/subject.tsp new file mode 100644 index 0000000000..aafcf39725 --- /dev/null +++ b/api/spec/packages/aip/src/events/subject.tsp @@ -0,0 +1,20 @@ +import "@typespec/openapi"; +import "@typespec/openapi3"; +import "../shared/index.tsp"; + +namespace Events; + +/** + * Subject of an event. + */ +@friendlyName("MeteringEventSubject") +model Subject { + /** + * The key of the subject. + */ + @minLength(1) + @visibility(Lifecycle.Read) + @summary("Key") + @example("customer-id") + key: string; +} diff --git a/api/spec/packages/aip/src/konnect.tsp b/api/spec/packages/aip/src/konnect.tsp index 5a51f812da..a3a4996de9 100644 --- a/api/spec/packages/aip/src/konnect.tsp +++ b/api/spec/packages/aip/src/konnect.tsp @@ -66,6 +66,10 @@ namespace MeteringAndBilling; @tag(Shared.EventsTag) interface EventsEndpoints extends Events.EventsOperations {} +@route("/openmeter/events/subjects") +@tag(Shared.EventsTag) +interface EventsSubjectsEndpoints extends Events.EventsSubjectsOperations {} + @route("/openmeter/meters") @tag(Shared.MetersTag) interface MetersEndpoints extends Meters.MetersOperations {} diff --git a/api/spec/packages/aip/src/openmeter.tsp b/api/spec/packages/aip/src/openmeter.tsp index 9bf16bc92d..0c4f87af31 100644 --- a/api/spec/packages/aip/src/openmeter.tsp +++ b/api/spec/packages/aip/src/openmeter.tsp @@ -71,6 +71,10 @@ namespace OpenMeter; @tag(Shared.EventsTag) interface EventsEndpoints extends Events.EventsOperations {} +@route("/openmeter/events/subjects") +@tag(Shared.EventsTag) +interface EventsSubjectsEndpoints extends Events.EventsSubjectsOperations {} + @route("/openmeter/meters") @tag(Shared.MetersTag) interface MetersEndpoints extends Meters.MetersOperations {} diff --git a/api/v3/api.gen.go b/api/v3/api.gen.go index 68ffd94641..e43183c8e7 100644 --- a/api/v3/api.gen.go +++ b/api/v3/api.gen.go @@ -3705,6 +3705,9 @@ type BillingWorkflowTaxSettings struct { Enforced *bool `json:"enforced,omitempty"` } +// BooleanFieldFilter Filter by a boolean value (true/false). +type BooleanFieldFilter = filters.FilterBoolean + // ChargePagePaginatedResponse Page paginated response. type ChargePagePaginatedResponse struct { Data []BillingCharge `json:"data"` @@ -4905,6 +4908,15 @@ type ListPlansParamsFilter struct { Status *StringFieldFilterExact `json:"status,omitempty"` } +// ListSubjectsParamsFilter Filter options for listing subjects. +type ListSubjectsParamsFilter struct { + // Attributed Filter subjects by whether they are attributed to a customer. + Attributed *BooleanFieldFilter `json:"attributed,omitempty"` + + // Key Filter subjects by key. + Key *StringFieldFilter `json:"key,omitempty"` +} + // ListSubscriptionsParamsFilter Filter options for listing subscriptions. type ListSubscriptionsParamsFilter struct { // CustomerId Filters on the given ULID field value by exact match. All properties are @@ -5095,6 +5107,12 @@ type MeteringEvent struct { // allowed over HTTP. type MeteringEventDatacontenttype string +// MeteringEventSubject Subject of an event. +type MeteringEventSubject struct { + // Key The key of the subject. + Key string `json:"key"` +} + // MeteringIngestedEvent An ingested metering event with ingestion metadata. type MeteringIngestedEvent struct { // Customer The customer if the event is associated with a customer. @@ -5344,6 +5362,14 @@ type StringFieldFilter = filters.FilterString // optional; provide exactly one to specify the comparison. type StringFieldFilterExact = filters.FilterStringExact +// SubjectPaginatedResponse Cursor paginated response. +type SubjectPaginatedResponse struct { + Data []MeteringEventSubject `json:"data"` + + // Meta Pagination metadata. + Meta CursorMeta `json:"meta"` +} + // SubscriptionAddon Addon purchased with a subscription. type SubscriptionAddon struct { // ActiveFrom An ISO-8601 timestamp representation of the cadence start of the resource. @@ -5864,6 +5890,17 @@ type IngestMeteringEventsJSONBody struct { // IngestMeteringEventsJSONBody1 defines parameters for IngestMeteringEvents. type IngestMeteringEventsJSONBody1 = []MeteringEvent +// ListEventSubjectsParams defines parameters for ListEventSubjects. +type ListEventSubjectsParams struct { + Page *CursorPaginationQuery `json:"page,omitempty"` + + // Filter Filter subjects returned in the response. + // + // To filter subjects by key add the following query param: + // filter[key][contains]=customer + Filter *ListSubjectsParamsFilter `json:"filter,omitempty"` +} + // ListFeaturesParams defines parameters for ListFeatures. type ListFeaturesParams struct { // Page Determines which page of the collection to retrieve. @@ -7291,6 +7328,9 @@ type ServerInterface interface { // Ingest metering events // (POST /openmeter/events) IngestMeteringEvents(w http.ResponseWriter, r *http.Request) + // List event subjects + // (GET /openmeter/events/subjects) + ListEventSubjects(w http.ResponseWriter, r *http.Request, params ListEventSubjectsParams) // List features // (GET /openmeter/features) ListFeatures(w http.ResponseWriter, r *http.Request, params ListFeaturesParams) @@ -7657,6 +7697,12 @@ func (_ Unimplemented) IngestMeteringEvents(w http.ResponseWriter, r *http.Reque w.WriteHeader(http.StatusNotImplemented) } +// List event subjects +// (GET /openmeter/events/subjects) +func (_ Unimplemented) ListEventSubjects(w http.ResponseWriter, r *http.Request, params ListEventSubjectsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + // List features // (GET /openmeter/features) func (_ Unimplemented) ListFeatures(w http.ResponseWriter, r *http.Request, params ListFeaturesParams) { @@ -8991,6 +9037,41 @@ func (siw *ServerInterfaceWrapper) IngestMeteringEvents(w http.ResponseWriter, r handler.ServeHTTP(w, r) } +// ListEventSubjects operation middleware +func (siw *ServerInterfaceWrapper) ListEventSubjects(w http.ResponseWriter, r *http.Request) { + + var err error + + // Parameter object where we will unmarshal all parameters from the context + var params ListEventSubjectsParams + + // ------------- Optional query parameter "page" ------------- + + err = runtime.BindQueryParameterWithOptions("deepObject", true, false, "page", r.URL.Query(), ¶ms.Page, runtime.BindQueryParameterOptions{Type: "object", Format: ""}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "page", Err: err}) + return + } + + // ------------- Optional query parameter "filter" ------------- + + err = filters.Parse(r.URL.Query(), ¶ms.Filter) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "filter", Err: err}) + return + } + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.ListEventSubjects(w, r, params) + })) + + for i := len(siw.HandlerMiddlewares) - 1; i >= 0; i-- { + handler = siw.HandlerMiddlewares[i](handler) + } + + handler.ServeHTTP(w, r) +} + // ListFeatures operation middleware func (siw *ServerInterfaceWrapper) ListFeatures(w http.ResponseWriter, r *http.Request) { @@ -10515,6 +10596,9 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl r.Group(func(r chi.Router) { r.Post(options.BaseURL+"/openmeter/events", wrapper.IngestMeteringEvents) }) + r.Group(func(r chi.Router) { + r.Get(options.BaseURL+"/openmeter/events/subjects", wrapper.ListEventSubjects) + }) r.Group(func(r chi.Router) { r.Get(options.BaseURL+"/openmeter/features", wrapper.ListFeatures) }) @@ -10666,668 +10750,674 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "I6aLiMkhBAA=", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v3/handlers/events/handler.go b/api/v3/handlers/events/handler.go index f8f440f546..911c1375b0 100644 --- a/api/v3/handlers/events/handler.go +++ b/api/v3/handlers/events/handler.go @@ -11,6 +11,7 @@ import ( type Handler interface { IngestEvents() IngestEventsHandler ListMeteringEvents() ListMeteringEventsHandler + ListEventSubjects() ListEventSubjectsHandler } type handler struct { diff --git a/api/v3/handlers/events/list_subjects.go b/api/v3/handlers/events/list_subjects.go new file mode 100644 index 0000000000..539fb8fbfc --- /dev/null +++ b/api/v3/handlers/events/list_subjects.go @@ -0,0 +1,159 @@ +package events + +import ( + "context" + "errors" + "fmt" + "net/http" + + "github.com/oapi-codegen/nullable" + "github.com/samber/lo" + + api "github.com/openmeterio/openmeter/api/v3" + "github.com/openmeterio/openmeter/api/v3/apierrors" + "github.com/openmeterio/openmeter/api/v3/filters" + "github.com/openmeterio/openmeter/api/v3/response" + "github.com/openmeterio/openmeter/openmeter/meterevent" + "github.com/openmeterio/openmeter/pkg/framework/commonhttp" + "github.com/openmeterio/openmeter/pkg/framework/transport/httptransport" + pagination "github.com/openmeterio/openmeter/pkg/pagination/v2" +) + +const defaultListEventSubjectsPageSize = 20 + +type ( + ListEventSubjectsRequest = meterevent.ListSubjectsParams + ListEventSubjectsResponse = response.CursorPaginationResponse[api.MeteringEventSubject] + ListEventSubjectsParams = api.ListEventSubjectsParams + ListEventSubjectsHandler httptransport.HandlerWithArgs[ListEventSubjectsRequest, ListEventSubjectsResponse, ListEventSubjectsParams] +) + +func (h *handler) ListEventSubjects() ListEventSubjectsHandler { + return httptransport.NewHandlerWithArgs( + func(ctx context.Context, r *http.Request, params ListEventSubjectsParams) (ListEventSubjectsRequest, error) { + ns, err := h.resolveNamespace(ctx) + if err != nil { + return ListEventSubjectsRequest{}, err + } + + req := ListEventSubjectsRequest{ + Namespace: ns, + } + + pageSize := defaultListEventSubjectsPageSize + if params.Page != nil { + if params.Page.Before != nil { + return ListEventSubjectsRequest{}, apierrors.NewBadRequestError(ctx, errors.New("page[before] is not supported"), apierrors.InvalidParameters{ + { + Field: "page[before]", + Reason: "backward pagination is not supported", + Source: apierrors.InvalidParamSourceQuery, + }, + }) + } + + if params.Page.After != nil { + cursor, err := pagination.DecodeCursor(*params.Page.After) + if err != nil { + return ListEventSubjectsRequest{}, apierrors.NewBadRequestError(ctx, err, apierrors.InvalidParameters{ + { + Field: "page[after]", + Reason: err.Error(), + Source: apierrors.InvalidParamSourceQuery, + }, + }) + } + req.Cursor = cursor + } + + if params.Page.Size != nil { + pageSize = *params.Page.Size + } + } + + if pageSize < 1 || pageSize > meterevent.MaximumLimit { + return ListEventSubjectsRequest{}, apierrors.NewBadRequestError(ctx, fmt.Errorf("page[size] must be between 1 and %d", meterevent.MaximumLimit), apierrors.InvalidParameters{ + { + Field: "page[size]", + Reason: fmt.Sprintf("must be between 1 and %d", meterevent.MaximumLimit), + Source: apierrors.InvalidParamSourceQuery, + }, + }) + } + req.Limit = lo.ToPtr(pageSize) + + if params.Filter != nil { + key, err := filters.FromAPIFilterString(params.Filter.Key) + if err != nil { + return ListEventSubjectsRequest{}, apierrors.NewBadRequestError(ctx, err, apierrors.InvalidParameters{ + { + Field: "filter[key]", + Reason: err.Error(), + Source: apierrors.InvalidParamSourceQuery, + }, + }) + } + req.Key = key + + attributed, err := filters.FromAPIFilterBoolean(params.Filter.Attributed) + if err != nil { + return ListEventSubjectsRequest{}, apierrors.NewBadRequestError(ctx, err, apierrors.InvalidParameters{ + { + Field: "filter[attributed]", + Reason: err.Error(), + Source: apierrors.InvalidParamSourceQuery, + }, + }) + } + if attributed != nil { + req.Attributed = attributed.Eq + } + } + + return req, nil + }, + func(ctx context.Context, req ListEventSubjectsRequest) (ListEventSubjectsResponse, error) { + result, err := h.metereventService.ListSubjects(ctx, req) + if err != nil { + return ListEventSubjectsResponse{}, err + } + + items := lo.Map(result.Items, func(s meterevent.Subject, _ int) api.MeteringEventSubject { + return api.MeteringEventSubject{ + Key: s.Key, + } + }) + + meta := response.CursorMeta{ + Page: response.CursorMetaPage{ + Next: nullable.NewNullNullable[string](), + Previous: nullable.NewNullNullable[string](), + Size: lo.FromPtrOr(req.Limit, defaultListEventSubjectsPageSize), + }, + } + + if len(result.Items) > 0 { + meta.Page.First = lo.ToPtr(result.Items[0].Cursor().Encode()) + meta.Page.Last = lo.ToPtr(result.Items[len(result.Items)-1].Cursor().Encode()) + } + + // The attributed filter is applied after pagination, so a full page does + // not imply more data and a short page does not imply exhaustion. The + // service-computed cursor is the only reliable continuation signal. + if result.NextCursor != nil { + meta.Page.Next = nullable.NewNullableWithValue(result.NextCursor.Encode()) + } + + return ListEventSubjectsResponse{ + Data: items, + Meta: meta, + }, nil + }, + commonhttp.JSONResponseEncoderWithStatus[ListEventSubjectsResponse](http.StatusOK), + httptransport.AppendOptions( + h.options, + httptransport.WithOperationName("list-event-subjects"), + httptransport.WithErrorEncoder(apierrors.GenericErrorEncoder()), + )..., + ) +} diff --git a/api/v3/openapi.yaml b/api/v3/openapi.yaml index c835c76baf..3743f73e16 100644 --- a/api/v3/openapi.yaml +++ b/api/v3/openapi.yaml @@ -1346,6 +1346,43 @@ paths: - type: array items: $ref: '#/components/schemas/MeteringEvent' + /openmeter/events/subjects: + get: + operationId: list-event-subjects + summary: List event subjects + description: |- + List the subjects of the ingested events. Subjects are ordered by key + alphabetically. + parameters: + - $ref: '#/components/parameters/CursorPaginationQuery' + - name: filter + in: query + required: false + description: |- + Filter subjects returned in the response. + + To filter subjects by key add the following query param: + filter[key][contains]=customer + schema: + $ref: '#/components/schemas/ListSubjectsParamsFilter' + style: deepObject + responses: + '200': + description: Cursor paginated response. + content: + application/json: + schema: + $ref: '#/components/schemas/SubjectPaginatedResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + tags: + - Metering Events + x-internal: true + x-unstable: true /openmeter/features: get: operationId: list-features @@ -6917,6 +6954,22 @@ components: additionalProperties: false description: Tax settings for a billing workflow. title: Workflow tax settings + BooleanFieldFilter: + anyOf: + - type: boolean + - type: object + properties: + eq: + type: boolean + description: Value strictly equals the given boolean value. + required: + - eq + additionalProperties: false + description: Filter by a boolean value (true/false). + title: Boolean Field Filter + x-go-type-import: + path: github.com/openmeterio/openmeter/api/v3/filters + x-go-type: filters.FilterBoolean ChargePagePaginatedResponse: type: object required: @@ -8603,6 +8656,19 @@ components: $ref: '#/components/schemas/StringFieldFilterExact' additionalProperties: false description: Filter options for listing plans. + ListSubjectsParamsFilter: + type: object + properties: + key: + allOf: + - $ref: '#/components/schemas/StringFieldFilter' + description: Filter subjects by key. + attributed: + allOf: + - $ref: '#/components/schemas/BooleanFieldFilter' + description: Filter subjects by whether they are attributed to a customer. + additionalProperties: false + description: Filter options for listing subjects. ListSubscriptionsParamsFilter: type: object properties: @@ -8962,6 +9028,20 @@ components: tokens: 100 model: gpt-4o type: input + MeteringEventSubject: + type: object + required: + - key + properties: + key: + type: string + minLength: 1 + description: The key of the subject. + title: Key + example: customer-id + readOnly: true + additionalProperties: false + description: Subject of an event. MeteringIngestedEvent: type: object required: @@ -9440,6 +9520,20 @@ components: x-go-type-import: path: github.com/openmeterio/openmeter/api/v3/filters x-go-type: filters.FilterStringExact + SubjectPaginatedResponse: + type: object + required: + - data + - meta + properties: + data: + type: array + items: + $ref: '#/components/schemas/MeteringEventSubject' + meta: + $ref: '#/components/schemas/CursorMeta' + additionalProperties: false + description: Cursor paginated response. SubscriptionAddon: type: object required: diff --git a/api/v3/server/routes.go b/api/v3/server/routes.go index d8f6afe50b..708501a32e 100644 --- a/api/v3/server/routes.go +++ b/api/v3/server/routes.go @@ -58,6 +58,10 @@ func (s *Server) ListMeteringEvents(w http.ResponseWriter, r *http.Request, para s.eventsHandler.ListMeteringEvents().With(params).ServeHTTP(w, r) } +func (s *Server) ListEventSubjects(w http.ResponseWriter, r *http.Request, params api.ListEventSubjectsParams) { + s.eventsHandler.ListEventSubjects().With(params).ServeHTTP(w, r) +} + // Customers func (s *Server) CreateCustomer(w http.ResponseWriter, r *http.Request) { diff --git a/app/common/streaming.go b/app/common/streaming.go index 19480defd1..7fdce7e1d5 100644 --- a/app/common/streaming.go +++ b/app/common/streaming.go @@ -32,17 +32,18 @@ func NewStreamingConnector( var err error connector, err = clickhouseconnector.New(ctx, clickhouseconnector.Config{ - ClickHouse: clickHouse, - Database: conf.ClickHouse.Database, - EventsTableName: conf.EventsTableName, - Logger: logger, - AsyncInsert: conf.AsyncInsert, - AsyncInsertWait: conf.AsyncInsertWait, - InsertQuerySettings: conf.InsertQuerySettings, - MeterQuerySettings: conf.MeterQuerySettings, - EnablePrewhere: conf.EnablePrewhere, - EnableDecimalPrecision: conf.EnableDecimalPrecision, - ProgressManager: progressmanager, + ClickHouse: clickHouse, + Database: conf.ClickHouse.Database, + EventsTableName: conf.EventsTableName, + Logger: logger, + AsyncInsert: conf.AsyncInsert, + AsyncInsertWait: conf.AsyncInsertWait, + InsertQuerySettings: conf.InsertQuerySettings, + MeterQuerySettings: conf.MeterQuerySettings, + EnablePrewhere: conf.EnablePrewhere, + EnableDecimalPrecision: conf.EnableDecimalPrecision, + ProgressManager: progressmanager, + CreateSubjectsProjection: conf.CreateSubjectsProjection, }) if err != nil { return nil, fmt.Errorf("init clickhouse connector: %w", err) diff --git a/app/config/aggregation.go b/app/config/aggregation.go index da77ccbb73..da7773b290 100644 --- a/app/config/aggregation.go +++ b/app/config/aggregation.go @@ -41,6 +41,13 @@ type AggregationConfiguration struct { // When enabled, values are calculated using Decimal128 instead of Float64, providing // higher precision for financial calculations at the cost of some performance. EnableDecimalPrecision bool + + // CreateSubjectsProjection adds an aggregate projection on the events table that + // pre-aggregates the distinct (namespace, subject) pairs, making the event subjects + // listing fast on large tables. Adding the projection only applies to newly inserted + // data; backfilling existing data requires running + // `ALTER TABLE MATERIALIZE PROJECTION prj_namespace_subject` manually. + CreateSubjectsProjection bool } // Validate validates the configuration. @@ -199,6 +206,7 @@ func ConfigureAggregation(v *viper.Viper) { v.SetDefault("aggregation.eventsTableName", "om_events") v.SetDefault("aggregation.asyncInsert", false) v.SetDefault("aggregation.asyncInsertWait", false) + v.SetDefault("aggregation.createSubjectsProjection", false) v.SetDefault("aggregation.clickhouse.address", "127.0.0.1:9000") v.SetDefault("aggregation.clickhouse.tls", false) diff --git a/e2e/events_subjects_v3_test.go b/e2e/events_subjects_v3_test.go new file mode 100644 index 0000000000..dcd8b876b6 --- /dev/null +++ b/e2e/events_subjects_v3_test.go @@ -0,0 +1,108 @@ +package e2e + +import ( + "net/http" + "net/url" + "testing" + "time" + + "github.com/brianvoe/gofakeit/v6" + "github.com/oapi-codegen/nullable" + "github.com/samber/lo" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + apiv3 "github.com/openmeterio/openmeter/api/v3" +) + +func TestEventSubjectsV3(t *testing.T) { + c := newV3Client(t) + + // Unique subject prefix so re-runs against a shared DB don't collide and + // the key filter only matches this test's fixtures. + prefix := uniqueKey("subj") + keys := []string{prefix + "_a", prefix + "_b", prefix + "_c"} + + now := time.Now() + events := make([]apiv3.MeteringEvent, 0, len(keys)) + for _, key := range keys { + events = append(events, apiv3.MeteringEvent{ + Id: gofakeit.UUID(), + Source: "e2e", + Specversion: "1.0", + Type: "ingest", + Subject: key, + Time: nullable.NewNullableWithValue[apiv3.DateTime](now), + Data: nullable.NewNullableWithValue(map[string]interface{}{"duration_ms": "100"}), + }) + } + + status, problem := c.IngestEvents(events) + require.Nil(t, problem, "ingest problem: %+v", problem) + require.Equal(t, http.StatusAccepted, status) + + // Attribute the middle subject to a customer so the attributed filter has + // both kinds of subjects to work with. + status, _, problem = c.CreateCustomer(apiv3.CreateCustomerRequest{ + Key: uniqueKey("subj_customer"), + Name: "Event Subjects Test Customer", + UsageAttribution: &apiv3.BillingCustomerUsageAttribution{ + SubjectKeys: []apiv3.UsageAttributionSubjectKey{keys[1]}, + }, + }) + require.Nil(t, problem, "create customer problem: %+v", problem) + require.Equal(t, http.StatusCreated, status) + + filterQuery := "?filter[key][contains]=" + url.QueryEscape(prefix) + + subjectKeys := func(resp *apiv3.SubjectPaginatedResponse) []string { + return lo.Map(resp.Data, func(s apiv3.MeteringEventSubject, _ int) string { return s.Key }) + } + + // Wait for the sink worker to land the events in ClickHouse. + assert.EventuallyWithT(t, func(t *assert.CollectT) { + status, resp, problem := c.ListEventSubjects(filterQuery) + require.Nil(t, problem, "list problem: %+v", problem) + require.Equal(t, http.StatusOK, status) + require.NotNil(t, resp) + + // Subjects are ordered by key ascending. + assert.Equal(t, keys, subjectKeys(resp)) + }, time.Minute, time.Second) + + t.Run("CursorPagination", func(t *testing.T) { + status, page1, problem := c.ListEventSubjects(filterQuery + "&page[size]=2") + require.Nil(t, problem, "list problem: %+v", problem) + require.Equal(t, http.StatusOK, status) + require.Equal(t, keys[:2], subjectKeys(page1)) + + next, err := page1.Meta.Page.Next.Get() + require.NoError(t, err, "full first page must carry a next cursor") + + status, page2, problem := c.ListEventSubjects(filterQuery + "&page[size]=2&page[after]=" + url.QueryEscape(next)) + require.Nil(t, problem, "list problem: %+v", problem) + require.Equal(t, http.StatusOK, status) + require.Equal(t, keys[2:], subjectKeys(page2)) + }) + + t.Run("AttributedFilter", func(t *testing.T) { + status, resp, problem := c.ListEventSubjects(filterQuery + "&filter[attributed][eq]=true") + require.Nil(t, problem, "list problem: %+v", problem) + require.Equal(t, http.StatusOK, status) + require.Equal(t, []string{keys[1]}, subjectKeys(resp)) + }) + + t.Run("UnattributedFilter", func(t *testing.T) { + status, resp, problem := c.ListEventSubjects(filterQuery + "&filter[attributed][eq]=false") + require.Nil(t, problem, "list problem: %+v", problem) + require.Equal(t, http.StatusOK, status) + require.Equal(t, []string{keys[0], keys[2]}, subjectKeys(resp)) + }) + + t.Run("KeyFilterNoMatch", func(t *testing.T) { + status, resp, problem := c.ListEventSubjects("?filter[key][contains]=" + url.QueryEscape(prefix+"_no_such_subject")) + require.Nil(t, problem, "list problem: %+v", problem) + require.Equal(t, http.StatusOK, status) + require.Empty(t, resp.Data) + }) +} diff --git a/e2e/v3helpers_test.go b/e2e/v3helpers_test.go index aba9583ad0..9467436711 100644 --- a/e2e/v3helpers_test.go +++ b/e2e/v3helpers_test.go @@ -162,6 +162,24 @@ func decodeTyped[T any](c *v3Client, status int, raw []byte, problem *v3Problem, return status, &v, nil } +// --- Events --- + +// IngestEvents posts a batch of metering events as application/json and +// returns the response status. Ingestion is asynchronous: events become +// visible to the metering-event endpoints once the sink worker lands them in +// ClickHouse. +func (c *v3Client) IngestEvents(events []apiv3.MeteringEvent) (int, *v3Problem) { + status, _, problem := c.do(http.MethodPost, "/events", events) + return status, problem +} + +// ListEventSubjects lists the subjects of the ingested events. query is the +// raw query string (including the leading "?"), or empty. +func (c *v3Client) ListEventSubjects(query string) (int, *apiv3.SubjectPaginatedResponse, *v3Problem) { + status, raw, problem := c.do(http.MethodGet, "/events/subjects"+query, nil) + return decodeTyped[apiv3.SubjectPaginatedResponse](c, status, raw, problem, http.StatusOK) +} + // --- Meters --- func (c *v3Client) CreateMeter(body apiv3.CreateMeterRequest) (int, *apiv3.Meter, *v3Problem) { diff --git a/openmeter/meterevent/adapter/subject.go b/openmeter/meterevent/adapter/subject.go new file mode 100644 index 0000000000..9f8c0c939f --- /dev/null +++ b/openmeter/meterevent/adapter/subject.go @@ -0,0 +1,136 @@ +package adapter + +import ( + "context" + "fmt" + "time" + + "github.com/samber/lo" + + "github.com/openmeterio/openmeter/openmeter/customer" + "github.com/openmeterio/openmeter/openmeter/meterevent" + "github.com/openmeterio/openmeter/openmeter/streaming" + "github.com/openmeterio/openmeter/pkg/filter" + "github.com/openmeterio/openmeter/pkg/models" + "github.com/openmeterio/openmeter/pkg/pagination/v2" +) + +// listSubjectsMaxScanRounds bounds how many streaming batches a single request +// scans when the attributed filter discards most of a batch. When the cap is +// hit, the result carries a next cursor so the client can continue scanning +// even though the page is not full. +const listSubjectsMaxScanRounds = 10 + +// ListSubjects returns the subjects of the ingested events ordered by key. +// +// The attributed filter is evaluated after resolving customer usage +// attribution, so the page is assembled by scanning streaming batches until it +// fills up, the subjects are exhausted, or the scan round cap is hit. A page +// shorter than the requested limit therefore does NOT imply the listing is +// exhausted; only an absent next cursor does. +func (a *adapter) ListSubjects(ctx context.Context, params meterevent.ListSubjectsParams) (pagination.Result[meterevent.Subject], error) { + // Validate input + if err := params.Validate(); err != nil { + return pagination.Result[meterevent.Subject]{}, models.NewGenericValidationError( + fmt.Errorf("validate input: %w", err), + ) + } + + limit := lo.FromPtrOr(params.Limit, meterevent.MaximumLimit) + + // Scanning one key past the limit proves whether more data follows a full + // page, so the next cursor can be decided without another batch. With the + // attributed filter, full-size batches fill the page in fewer rounds. + scanLimit := limit + 1 + if params.Attributed != nil { + scanLimit = meterevent.MaximumLimit + } + + result := pagination.Result[meterevent.Subject]{Items: make([]meterevent.Subject, 0, limit)} + cursor := params.Cursor + + for range listSubjectsMaxScanRounds { + // Get the next batch of subject keys + keys, err := a.streamingConnector.ListSubjectsV2(ctx, streaming.ListSubjectsV2Params{ + Namespace: params.Namespace, + Key: params.Key, + Cursor: cursor, + Limit: &scanLimit, + }) + if err != nil { + return pagination.Result[meterevent.Subject]{}, fmt.Errorf("query subjects: %w", err) + } + + // Attribution is only resolved when the attributed filter needs it. + var attributedKeys map[string]struct{} + if params.Attributed != nil { + attributedKeys, err = a.attributedSubjectKeys(ctx, params.Namespace, keys) + if err != nil { + return pagination.Result[meterevent.Subject]{}, fmt.Errorf("resolve attributed subjects: %w", err) + } + } + + for _, key := range keys { + if params.Attributed != nil && *params.Attributed != lo.HasKey(attributedKeys, key) { + continue + } + + result.Items = append(result.Items, meterevent.Subject{Key: key}) + } + + // A match beyond the limit proves more data follows the trimmed page. + if len(result.Items) > limit { + result.Items = result.Items[:limit] + result.NextCursor = lo.ToPtr(result.Items[limit-1].Cursor()) + + return result, nil + } + + // The batch was the last one; whatever matched is the final page. + if len(keys) < scanLimit { + return result, nil + } + + cursor = lo.ToPtr(pagination.NewCursor(time.Time{}, keys[len(keys)-1])) + } + + // Scan round cap hit: resume from the last scanned subject key. + result.NextCursor = cursor + + return result, nil +} + +// attributedSubjectKeys resolves which subject keys are attributed to a customer. +// Usage attribution matches a subject key against either the customer's usage +// attribution subject keys or the customer's own key. +func (a *adapter) attributedSubjectKeys(ctx context.Context, namespace string, keys []string) (map[string]struct{}, error) { + attributed := map[string]struct{}{} + + if len(keys) == 0 { + return attributed, nil + } + + for _, input := range []customer.ListCustomersInput{ + { + Namespace: namespace, + UsageAttributionSubjectKey: &filter.FilterString{In: &keys}, + }, + { + Namespace: namespace, + Key: &filter.FilterString{In: &keys}, + }, + } { + customerList, err := a.customerService.ListCustomers(ctx, input) + if err != nil { + return nil, fmt.Errorf("list customers: %w", err) + } + + for _, c := range customerList.Items { + for _, value := range c.GetUsageAttribution().GetValues() { + attributed[value] = struct{}{} + } + } + } + + return attributed, nil +} diff --git a/openmeter/meterevent/adapter/subject_test.go b/openmeter/meterevent/adapter/subject_test.go new file mode 100644 index 0000000000..f7a1b3c89b --- /dev/null +++ b/openmeter/meterevent/adapter/subject_test.go @@ -0,0 +1,223 @@ +package adapter + +import ( + "context" + "fmt" + "testing" + + "github.com/samber/lo" + "github.com/stretchr/testify/require" + + "github.com/openmeterio/openmeter/openmeter/customer" + "github.com/openmeterio/openmeter/openmeter/meterevent" + "github.com/openmeterio/openmeter/openmeter/streaming" + "github.com/openmeterio/openmeter/pkg/models" + "github.com/openmeterio/openmeter/pkg/pagination" +) + +// fakeStreamingConnector serves ListSubjectsV2 from an in-memory sorted key +// list, honoring the keyset cursor and limit like the ClickHouse query does. +type fakeStreamingConnector struct { + streaming.Connector + + keys []string + calls int +} + +func (f *fakeStreamingConnector) ListSubjectsV2(_ context.Context, params streaming.ListSubjectsV2Params) ([]string, error) { + f.calls++ + + limit := lo.FromPtr(params.Limit) + + page := []string{} + for _, key := range f.keys { + if params.Cursor != nil && key <= params.Cursor.ID { + continue + } + if len(page) == limit { + break + } + page = append(page, key) + } + + return page, nil +} + +// fakeCustomerService resolves usage attribution from a subject key → +// customer ID map. Each mapping is exposed as a distinct customer whose usage +// attribution subject keys contain the subject key. +type fakeCustomerService struct { + customer.Service + + customerIDBySubjectKey map[string]string +} + +func (f *fakeCustomerService) ListCustomers(_ context.Context, input customer.ListCustomersInput) (pagination.Result[customer.Customer], error) { + var items []customer.Customer + + // Only the usage-attribution lookup resolves customers in this fake; the + // customer-key lookup returns no matches. + if input.UsageAttributionSubjectKey != nil && input.UsageAttributionSubjectKey.In != nil { + for _, key := range *input.UsageAttributionSubjectKey.In { + if customerID, ok := f.customerIDBySubjectKey[key]; ok { + items = append(items, customer.Customer{ + ManagedResource: models.ManagedResource{ID: customerID}, + UsageAttribution: &customer.CustomerUsageAttribution{ + SubjectKeys: []string{key}, + }, + }) + } + } + } + + return pagination.Result[customer.Customer]{Items: items, TotalCount: len(items)}, nil +} + +func TestListSubjects(t *testing.T) { + newAdapter := func(keys []string, attribution map[string]string) (*adapter, *fakeStreamingConnector) { + connector := &fakeStreamingConnector{keys: keys} + return &adapter{ + streamingConnector: connector, + customerService: &fakeCustomerService{customerIDBySubjectKey: attribution}, + }, connector + } + + t.Run("WithoutAttributedFilterSingleBatch", func(t *testing.T) { + // given: + // - three subjects, the middle one attributed to a customer + // when: + // - listing without the attributed filter + // then: + // - all subjects are returned in one streaming batch, no next cursor + a, connector := newAdapter([]string{"s1", "s2", "s3"}, map[string]string{"s2": "customer-2"}) + + result, err := a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(10), + }) + require.NoError(t, err) + + require.Equal(t, []meterevent.Subject{ + {Key: "s1"}, + {Key: "s2"}, + {Key: "s3"}, + }, result.Items) + require.Nil(t, result.NextCursor) + require.Equal(t, 1, connector.calls) + }) + + t.Run("FullPageEmitsNextCursor", func(t *testing.T) { + a, _ := newAdapter([]string{"s1", "s2", "s3"}, nil) + + result, err := a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(2), + }) + require.NoError(t, err) + + require.Len(t, result.Items, 2) + require.NotNil(t, result.NextCursor) + require.Equal(t, "s2", result.NextCursor.ID) + + // The follow-up page returns the remainder without a next cursor. + result, err = a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(2), + Cursor: result.NextCursor, + }) + require.NoError(t, err) + require.Equal(t, []meterevent.Subject{{Key: "s3"}}, result.Items) + require.Nil(t, result.NextCursor) + }) + + t.Run("AttributedFilterScansAcrossBatches", func(t *testing.T) { + // given: + // - 250 subjects spanning multiple streaming batches, every tenth one attributed + keys := make([]string, 0, 250) + attribution := map[string]string{} + for i := range 250 { + key := fmt.Sprintf("s%03d", i) + keys = append(keys, key) + if i%10 == 0 { + attribution[key] = "customer-" + key + } + } + + a, connector := newAdapter(keys, attribution) + + // when: + // - listing attributed subjects with a page size larger than one batch yields + // then: + // - the scan crosses batches until the page fills and continues via the cursor + result, err := a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(15), + Attributed: lo.ToPtr(true), + }) + require.NoError(t, err) + + require.Len(t, result.Items, 15) + for _, subject := range result.Items { + require.Contains(t, attribution, subject.Key, "subject %s must be attributed", subject.Key) + } + require.Greater(t, connector.calls, 1) + require.NotNil(t, result.NextCursor) + require.Equal(t, "s140", result.NextCursor.ID) + + // The follow-up page returns the remaining 10 attributed subjects and + // reports exhaustion. + result, err = a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(15), + Attributed: lo.ToPtr(true), + Cursor: result.NextCursor, + }) + require.NoError(t, err) + require.Len(t, result.Items, 10) + require.Nil(t, result.NextCursor) + }) + + t.Run("UnattributedFilterDropsAttributedSubjects", func(t *testing.T) { + a, _ := newAdapter([]string{"s1", "s2", "s3"}, map[string]string{"s2": "customer-2"}) + + result, err := a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(10), + Attributed: lo.ToPtr(false), + }) + require.NoError(t, err) + + require.Equal(t, []meterevent.Subject{{Key: "s1"}, {Key: "s3"}}, result.Items) + require.Nil(t, result.NextCursor) + }) + + t.Run("ScanRoundCapReturnsContinuationCursor", func(t *testing.T) { + // given: + // - more fully-attributed subjects than the scan cap covers (10 rounds x 100) + keys := make([]string, 0, 1100) + attribution := map[string]string{} + for i := range 1100 { + key := fmt.Sprintf("s%04d", i) + keys = append(keys, key) + attribution[key] = "customer-" + key + } + + a, connector := newAdapter(keys, attribution) + + // when: + // - listing unattributed subjects, which never match + // then: + // - the scan stops at the round cap with an empty page and a continuation cursor + result, err := a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(10), + Attributed: lo.ToPtr(false), + }) + require.NoError(t, err) + + require.Empty(t, result.Items) + require.Equal(t, listSubjectsMaxScanRounds, connector.calls) + require.NotNil(t, result.NextCursor) + require.Equal(t, "s0999", result.NextCursor.ID) + }) +} diff --git a/openmeter/meterevent/service.go b/openmeter/meterevent/service.go index 1e5d632a7e..6cf01cc60c 100644 --- a/openmeter/meterevent/service.go +++ b/openmeter/meterevent/service.go @@ -20,6 +20,7 @@ const ( type Service interface { ListEvents(ctx context.Context, params ListEventsParams) ([]Event, error) ListEventsV2(ctx context.Context, params ListEventsV2Params) (pagination.Result[Event], error) + ListSubjects(ctx context.Context, params ListSubjectsParams) (pagination.Result[Subject], error) } // ListEventsParams represents the input for ListEvents method. diff --git a/openmeter/meterevent/subject.go b/openmeter/meterevent/subject.go new file mode 100644 index 0000000000..5c14c31d18 --- /dev/null +++ b/openmeter/meterevent/subject.go @@ -0,0 +1,67 @@ +package meterevent + +import ( + "errors" + "fmt" + "time" + + "github.com/openmeterio/openmeter/pkg/filter" + "github.com/openmeterio/openmeter/pkg/pagination/v2" +) + +// Subject represents a subject that has ingested events. +type Subject struct { + // The subject key. + Key string +} + +var _ pagination.Item = (*Subject)(nil) + +// Cursor returns the cursor for the subject. Subjects are ordered by key, so the +// cursor carries the key in its ID part; the time part is unused. +func (s Subject) Cursor() pagination.Cursor { + return pagination.NewCursor(time.Time{}, s.Key) +} + +// ListSubjectsParams is a parameter object for listing subjects. +type ListSubjectsParams struct { + // The namespace. + Namespace string + // The cursor. + Cursor *pagination.Cursor + // The limit. + Limit *int + // The subject key filter. + Key *filter.FilterString + // Attributed filters subjects by whether they are attributed to a customer. + Attributed *bool +} + +// Validate validates the list subjects parameters. +func (p ListSubjectsParams) Validate() error { + var errs []error + + if p.Namespace == "" { + errs = append(errs, errors.New("namespace is required")) + } + + if p.Cursor != nil && p.Cursor.ID == "" { + errs = append(errs, errors.New("cursor id is required")) + } + + if p.Key != nil { + if err := p.Key.ValidateWithComplexity(1); err != nil { + errs = append(errs, fmt.Errorf("key: %w", err)) + } + } + + if p.Limit != nil && *p.Limit < 1 { + errs = append(errs, errors.New("limit must be greater than 0")) + } + + if p.Limit != nil && *p.Limit > MaximumLimit { + errs = append(errs, fmt.Errorf("limit must be less than or equal to %d", MaximumLimit)) + } + + return errors.Join(errs...) +} diff --git a/openmeter/meterevent/subject_test.go b/openmeter/meterevent/subject_test.go new file mode 100644 index 0000000000..6eb8298940 --- /dev/null +++ b/openmeter/meterevent/subject_test.go @@ -0,0 +1,103 @@ +package meterevent_test + +import ( + "testing" + "time" + + "github.com/samber/lo" + "github.com/stretchr/testify/require" + + "github.com/openmeterio/openmeter/openmeter/meterevent" + "github.com/openmeterio/openmeter/pkg/filter" + "github.com/openmeterio/openmeter/pkg/pagination/v2" +) + +func TestListSubjectsParams_Validate(t *testing.T) { + tests := []struct { + name string + params meterevent.ListSubjectsParams + wantErr bool + }{ + { + name: "namespace required", + params: meterevent.ListSubjectsParams{}, + wantErr: true, + }, + { + name: "valid with no filters", + params: meterevent.ListSubjectsParams{ + Namespace: "my_namespace", + }, + }, + { + name: "key filter is accepted", + params: meterevent.ListSubjectsParams{ + Namespace: "my_namespace", + Key: &filter.FilterString{ + Contains: lo.ToPtr("customer"), + }, + }, + }, + { + name: "cursor without id is rejected", + params: meterevent.ListSubjectsParams{ + Namespace: "my_namespace", + Cursor: &pagination.Cursor{}, + }, + wantErr: true, + }, + { + name: "valid cursor is accepted", + params: meterevent.ListSubjectsParams{ + Namespace: "my_namespace", + Cursor: lo.ToPtr(meterevent.Subject{Key: "customer-1"}.Cursor()), + }, + }, + { + name: "limit over maximum is rejected", + params: meterevent.ListSubjectsParams{ + Namespace: "my_namespace", + Limit: lo.ToPtr(meterevent.MaximumLimit + 1), + }, + wantErr: true, + }, + { + name: "zero limit is rejected", + params: meterevent.ListSubjectsParams{ + Namespace: "my_namespace", + Limit: lo.ToPtr(0), + }, + wantErr: true, + }, + { + name: "negative limit is rejected", + params: meterevent.ListSubjectsParams{ + Namespace: "my_namespace", + Limit: lo.ToPtr(-1), + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.params.Validate() + if !tt.wantErr { + require.NoError(t, err) + return + } + require.Error(t, err) + }) + } +} + +func TestSubject_Cursor(t *testing.T) { + cursor := meterevent.Subject{Key: "customer-1"}.Cursor() + + // The cursor must round-trip through its encoded form so keyset pagination + // can resume from the subject key. + decoded, err := pagination.DecodeCursor(cursor.Encode()) + require.NoError(t, err) + require.Equal(t, "customer-1", decoded.ID) + require.True(t, decoded.Time.Equal(time.Time{})) +} diff --git a/openmeter/server/server_test.go b/openmeter/server/server_test.go index 429c04136d..9cd6be0d93 100644 --- a/openmeter/server/server_test.go +++ b/openmeter/server/server_test.go @@ -1003,6 +1003,10 @@ func (c *MockStreamingConnector) ListSubjects(ctx context.Context, params stream return []string{"s1"}, nil } +func (c *MockStreamingConnector) ListSubjectsV2(ctx context.Context, params streaming.ListSubjectsV2Params) ([]string, error) { + return []string{"s1"}, nil +} + func (c *MockStreamingConnector) ListGroupByValues(ctx context.Context, params streaming.ListGroupByValuesParams) ([]string, error) { return []string{"v1"}, nil } diff --git a/openmeter/streaming/clickhouse/connector.go b/openmeter/streaming/clickhouse/connector.go index 837ba886f2..af9b70ba34 100644 --- a/openmeter/streaming/clickhouse/connector.go +++ b/openmeter/streaming/clickhouse/connector.go @@ -38,6 +38,13 @@ type Config struct { EnableDecimalPrecision bool ProgressManager progressmanager.Service SkipCreateTables bool + + // CreateSubjectsProjection adds an aggregate projection on the events table that + // pre-aggregates the distinct (namespace, subject) pairs, making the subjects + // listing fast on large tables. The projection only applies to newly inserted + // data; backfilling existing data requires manually running + // `ALTER TABLE MATERIALIZE PROJECTION prj_namespace_subject`. + CreateSubjectsProjection bool } func (c Config) Validate() error { @@ -92,6 +99,17 @@ func (c *Connector) createTable(ctx context.Context) error { return fmt.Errorf("create events table in clickhouse: %w", err) } + if c.config.CreateSubjectsProjection { + projection := createEventsSubjectsProjection{ + Database: c.config.Database, + EventsTableName: c.config.EventsTableName, + } + + if err := c.config.ClickHouse.Exec(ctx, projection.toSQL()); err != nil { + return fmt.Errorf("create events subjects projection in clickhouse: %w", err) + } + } + return nil } @@ -214,6 +232,19 @@ func (c *Connector) ListSubjects(ctx context.Context, params streaming.ListSubje return subjects, nil } +func (c *Connector) ListSubjectsV2(ctx context.Context, params streaming.ListSubjectsV2Params) ([]string, error) { + if err := params.Validate(); err != nil { + return nil, fmt.Errorf("validate params: %w", err) + } + + subjects, err := c.listSubjectsV2(ctx, params) + if err != nil { + return nil, fmt.Errorf("list subjects v2: %w", err) + } + + return subjects, nil +} + func (c *Connector) ListGroupByValues(ctx context.Context, params streaming.ListGroupByValuesParams) ([]string, error) { if err := params.Validate(); err != nil { return nil, fmt.Errorf("validate params: %w", err) @@ -569,6 +600,40 @@ func (c *Connector) listSubjects(ctx context.Context, params streaming.ListSubje return subjects, nil } +// listSubjectsV2 lists the subjects that have events in the database with keyset pagination +func (c *Connector) listSubjectsV2(ctx context.Context, params streaming.ListSubjectsV2Params) ([]string, error) { + query := listSubjectsV2Query{ + Database: c.config.Database, + EventsTableName: c.config.EventsTableName, + Params: params, + } + + sql, args := query.toSQL() + + rows, err := c.config.ClickHouse.Query(ctx, sql, args...) + if err != nil { + return nil, fmt.Errorf("query subjects: %w", err) + } + + defer rows.Close() + + subjects := []string{} + for rows.Next() { + var subject string + if err = rows.Scan(&subject); err != nil { + return nil, err + } + + subjects = append(subjects, subject) + } + + if err = rows.Err(); err != nil { + return nil, fmt.Errorf("rows error: %w", err) + } + + return subjects, nil +} + // listGroupByValues lists the group by values that have events in the database func (c *Connector) listGroupByValues(ctx context.Context, params streaming.ListGroupByValuesParams) ([]string, error) { query := listGroupByValuesQuery{ diff --git a/openmeter/streaming/clickhouse/subject_query.go b/openmeter/streaming/clickhouse/subject_query.go index 71d5b754d0..95554ccac1 100644 --- a/openmeter/streaming/clickhouse/subject_query.go +++ b/openmeter/streaming/clickhouse/subject_query.go @@ -5,8 +5,10 @@ import ( "time" "github.com/huandu/go-sqlbuilder" + "github.com/samber/lo" meterpkg "github.com/openmeterio/openmeter/openmeter/meter" + "github.com/openmeterio/openmeter/openmeter/streaming" ) type listSubjectsQuery struct { @@ -49,3 +51,64 @@ func (d listSubjectsQuery) toSQL() (string, []interface{}) { sql, args := sb.Build() return sql, args } + +const listSubjectsV2DefaultLimit = 100 + +// eventsSubjectsProjectionName is the aggregate projection on the events table +// that pre-aggregates the distinct (namespace, subject) pairs. +const eventsSubjectsProjectionName = "prj_namespace_subject" + +// createEventsSubjectsProjection adds the events subjects projection. +// Adding the projection only applies to newly inserted data; backfilling +// existing data requires manually running +// `ALTER TABLE MATERIALIZE PROJECTION prj_namespace_subject`. +type createEventsSubjectsProjection struct { + Database string + EventsTableName string +} + +func (d createEventsSubjectsProjection) toSQL() string { + tableName := getTableName(d.Database, d.EventsTableName) + + return fmt.Sprintf( + "ALTER TABLE %s ADD PROJECTION IF NOT EXISTS %s (SELECT namespace, subject GROUP BY namespace, subject)", + tableName, + eventsSubjectsProjectionName, + ) +} + +type listSubjectsV2Query struct { + Database string + EventsTableName string + Params streaming.ListSubjectsV2Params +} + +// toSQL builds the subjects listing query. It uses GROUP BY instead of +// DISTINCT so ClickHouse can serve it from the events subjects projection +// (when present) instead of scanning the events table. +func (d listSubjectsV2Query) toSQL() (string, []interface{}) { + tableName := getTableName(d.Database, d.EventsTableName) + + query := sqlbuilder.ClickHouse.NewSelectBuilder() + query.Select("subject") + query.From(tableName) + query.Where(query.Equal("namespace", d.Params.Namespace)) + + if d.Params.Key != nil { + expr := d.Params.Key.SelectWhereExpr("subject", query) + if expr != "" { + query.Where(expr) + } + } + + // Keyset pagination: the cursor ID holds the last subject key of the previous page. + if d.Params.Cursor != nil { + query.Where(query.GreaterThan("subject", d.Params.Cursor.ID)) + } + + query.GroupBy("namespace", "subject") + query.OrderBy("namespace", "subject") + query.Limit(lo.FromPtrOr(d.Params.Limit, listSubjectsV2DefaultLimit)) + + return query.Build() +} diff --git a/openmeter/streaming/clickhouse/subject_query_test.go b/openmeter/streaming/clickhouse/subject_query_test.go index b4be117b3c..7b9f675c20 100644 --- a/openmeter/streaming/clickhouse/subject_query_test.go +++ b/openmeter/streaming/clickhouse/subject_query_test.go @@ -8,6 +8,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/openmeterio/openmeter/openmeter/meter" + "github.com/openmeterio/openmeter/openmeter/streaming" + "github.com/openmeterio/openmeter/pkg/filter" + "github.com/openmeterio/openmeter/pkg/pagination/v2" ) func TestListSubjects(t *testing.T) { @@ -101,3 +104,74 @@ func TestListSubjects(t *testing.T) { }) } } + +func TestListSubjectsV2(t *testing.T) { + tests := []struct { + name string + query listSubjectsV2Query + wantSQL string + wantArgs []interface{} + }{ + { + name: "basic query", + query: listSubjectsV2Query{ + Database: "openmeter", + EventsTableName: "om_events", + Params: streaming.ListSubjectsV2Params{ + Namespace: "my_namespace", + }, + }, + wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", + wantArgs: []interface{}{"my_namespace", 100}, + }, + { + name: "query with key filter", + query: listSubjectsV2Query{ + Database: "openmeter", + EventsTableName: "om_events", + Params: streaming.ListSubjectsV2Params{ + Namespace: "my_namespace", + Key: &filter.FilterString{Ilike: lo.ToPtr("%customer%")}, + }, + }, + wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND LOWER(subject) LIKE LOWER(?) GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", + wantArgs: []interface{}{"my_namespace", "%customer%", 100}, + }, + { + name: "query with cursor and limit", + query: listSubjectsV2Query{ + Database: "openmeter", + EventsTableName: "om_events", + Params: streaming.ListSubjectsV2Params{ + Namespace: "my_namespace", + Cursor: lo.ToPtr(pagination.NewCursor(time.Time{}, "customer-1")), + Limit: lo.ToPtr(10), + }, + }, + wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND subject > ? GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", + wantArgs: []interface{}{"my_namespace", "customer-1", 10}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotSql, gotArgs := tt.query.toSQL() + + assert.Equal(t, tt.wantArgs, gotArgs) + assert.Equal(t, tt.wantSQL, gotSql) + }) + } +} + +func TestCreateEventsSubjectsProjection(t *testing.T) { + projection := createEventsSubjectsProjection{ + Database: "openmeter", + EventsTableName: "om_events", + } + + assert.Equal( + t, + "ALTER TABLE openmeter.om_events ADD PROJECTION IF NOT EXISTS prj_namespace_subject (SELECT namespace, subject GROUP BY namespace, subject)", + projection.toSQL(), + ) +} diff --git a/openmeter/streaming/connector.go b/openmeter/streaming/connector.go index 32559395de..4ae378b32e 100644 --- a/openmeter/streaming/connector.go +++ b/openmeter/streaming/connector.go @@ -3,11 +3,14 @@ package streaming import ( "context" "errors" + "fmt" "time" "github.com/openmeterio/openmeter/openmeter/meter" "github.com/openmeterio/openmeter/openmeter/namespace" + "github.com/openmeterio/openmeter/pkg/filter" "github.com/openmeterio/openmeter/pkg/models" + "github.com/openmeterio/openmeter/pkg/pagination/v2" ) type CountEventsParams struct { @@ -43,6 +46,9 @@ type Connector interface { ListEventsV2(ctx context.Context, params ListEventsV2Params) ([]RawEvent, error) // ListSubjects lists the subjects that have events in the database ListSubjects(ctx context.Context, params ListSubjectsParams) ([]string, error) + // ListSubjectsV2 lists the subjects that have events in the database, + // ordered by subject key ascending with keyset pagination. + ListSubjectsV2(ctx context.Context, params ListSubjectsV2Params) ([]string, error) // ListGroupByValues lists the group by values that have events in the database ListGroupByValues(ctx context.Context, params ListGroupByValuesParams) ([]string, error) QueryMeter(ctx context.Context, namespace string, meter meter.Meter, params QueryParams) ([]meter.MeterQueryRow, error) @@ -86,6 +92,43 @@ func (p ListSubjectsParams) Validate() error { return models.NewNillableGenericValidationError(errors.Join(errs...)) } +// ListSubjectsV2Params is a parameter object for listing subjects with keyset pagination. +type ListSubjectsV2Params struct { + // The namespace. + Namespace string + // The subject key filter. + Key *filter.FilterString + // The cursor. Only the ID part is used: it holds the last subject key of the previous page. + Cursor *pagination.Cursor + // The limit. + Limit *int +} + +// Validate validates the list subjects v2 parameters. +func (p ListSubjectsV2Params) Validate() error { + var errs []error + + if p.Namespace == "" { + errs = append(errs, errors.New("namespace is required")) + } + + if p.Key != nil { + if err := p.Key.ValidateWithComplexity(1); err != nil { + errs = append(errs, fmt.Errorf("key: %w", err)) + } + } + + if p.Cursor != nil && p.Cursor.ID == "" { + errs = append(errs, errors.New("cursor id is required")) + } + + if p.Limit != nil && *p.Limit < 1 { + errs = append(errs, errors.New("limit must be greater than 0")) + } + + return models.NewNillableGenericValidationError(errors.Join(errs...)) +} + // ListGroupByValuesParams is a parameter object for listing group by values. type ListGroupByValuesParams struct { Namespace string diff --git a/openmeter/streaming/retry/retry.go b/openmeter/streaming/retry/retry.go index 3c2e91c480..b4eac7e14c 100644 --- a/openmeter/streaming/retry/retry.go +++ b/openmeter/streaming/retry/retry.go @@ -103,6 +103,12 @@ func (c *Connector) ListSubjects(ctx context.Context, params streaming.ListSubje }) } +func (c *Connector) ListSubjectsV2(ctx context.Context, params streaming.ListSubjectsV2Params) ([]string, error) { + return withRetry(ctx, c, func() ([]string, error) { + return c.downstreamConnector.ListSubjectsV2(ctx, params) + }) +} + func (c *Connector) ListGroupByValues(ctx context.Context, params streaming.ListGroupByValuesParams) ([]string, error) { return withRetry(ctx, c, func() ([]string, error) { return c.downstreamConnector.ListGroupByValues(ctx, params) diff --git a/openmeter/streaming/testutils/streaming.go b/openmeter/streaming/testutils/streaming.go index b6632fdd61..c609a98358 100644 --- a/openmeter/streaming/testutils/streaming.go +++ b/openmeter/streaming/testutils/streaming.go @@ -284,6 +284,10 @@ func (m *MockStreamingConnector) ListSubjects(ctx context.Context, params stream return []string{}, nil } +func (m *MockStreamingConnector) ListSubjectsV2(ctx context.Context, params streaming.ListSubjectsV2Params) ([]string, error) { + return []string{}, nil +} + func (m *MockStreamingConnector) ListGroupByValues(ctx context.Context, params streaming.ListGroupByValuesParams) ([]string, error) { return []string{}, nil } From 72ee5e2c7754c203fc1841c02bbe7be6260b3aeb Mon Sep 17 00:00:00 2001 From: Andras Toth <4157749+tothandras@users.noreply.github.com> Date: Fri, 12 Jun 2026 12:27:22 +0200 Subject: [PATCH 2/2] refactor: WIP --- e2e/config.yaml | 3 ++ e2e/events_subjects_v3_test.go | 18 +++++++ openmeter/meterevent/adapter/subject.go | 5 ++ openmeter/meterevent/adapter/subject_test.go | 47 ++++++++++++++++--- openmeter/streaming/clickhouse/connector.go | 1 + .../streaming/clickhouse/subject_query.go | 19 ++++++++ .../clickhouse/subject_query_test.go | 25 +++++++--- 7 files changed, 106 insertions(+), 12 deletions(-) diff --git a/e2e/config.yaml b/e2e/config.yaml index a2803b647d..98fc7de9b5 100644 --- a/e2e/config.yaml +++ b/e2e/config.yaml @@ -15,6 +15,9 @@ ingest: broker: kafka:9092 aggregation: + # Exercise the events subjects projection DDL and the projection-served + # listing path in CI. + createSubjectsProjection: true clickhouse: address: clickhouse:9000 retry: diff --git a/e2e/events_subjects_v3_test.go b/e2e/events_subjects_v3_test.go index dcd8b876b6..a14858208c 100644 --- a/e2e/events_subjects_v3_test.go +++ b/e2e/events_subjects_v3_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" apiv3 "github.com/openmeterio/openmeter/api/v3" + pagination "github.com/openmeterio/openmeter/pkg/pagination/v2" ) func TestEventSubjectsV3(t *testing.T) { @@ -83,6 +84,23 @@ func TestEventSubjectsV3(t *testing.T) { require.Nil(t, problem, "list problem: %+v", problem) require.Equal(t, http.StatusOK, status) require.Equal(t, keys[2:], subjectKeys(page2)) + + // Only an absent next cursor signals exhaustion; a short page does not. + _, err = page2.Meta.Page.Next.Get() + require.Error(t, err, "exhausted listing must not carry a next cursor") + }) + + t.Run("InvalidParams", func(t *testing.T) { + for _, query := range []string{ + "?page[before]=" + url.QueryEscape(pagination.NewCursor(time.Time{}, "x").Encode()), + "?page[after]=not-a-cursor", + "?page[size]=0", + "?page[size]=101", + "?filter[attributed][eq]=notabool", + } { + status, _, problem := c.ListEventSubjects(query) + require.Equal(t, http.StatusBadRequest, status, "query %q must be rejected: %+v", query, problem) + } }) t.Run("AttributedFilter", func(t *testing.T) { diff --git a/openmeter/meterevent/adapter/subject.go b/openmeter/meterevent/adapter/subject.go index 9f8c0c939f..9509e5530b 100644 --- a/openmeter/meterevent/adapter/subject.go +++ b/openmeter/meterevent/adapter/subject.go @@ -106,6 +106,11 @@ func (a *adapter) ListSubjects(ctx context.Context, params meterevent.ListSubjec func (a *adapter) attributedSubjectKeys(ctx context.Context, namespace string, keys []string) (map[string]struct{}, error) { attributed := map[string]struct{}{} + // The streaming query excludes empty subjects, but rows from direct + // producers must not reach the customer filters: pkg/filter rejects empty + // values, which would fail the whole listing. + keys = lo.Filter(keys, func(key string, _ int) bool { return key != "" }) + if len(keys) == 0 { return attributed, nil } diff --git a/openmeter/meterevent/adapter/subject_test.go b/openmeter/meterevent/adapter/subject_test.go index f7a1b3c89b..f87419b46b 100644 --- a/openmeter/meterevent/adapter/subject_test.go +++ b/openmeter/meterevent/adapter/subject_test.go @@ -43,20 +43,20 @@ func (f *fakeStreamingConnector) ListSubjectsV2(_ context.Context, params stream return page, nil } -// fakeCustomerService resolves usage attribution from a subject key → -// customer ID map. Each mapping is exposed as a distinct customer whose usage -// attribution subject keys contain the subject key. +// fakeCustomerService resolves attribution from subject key → customer ID and +// customer key → customer ID maps, mirroring the two lookups +// attributedSubjectKeys performs: customers whose usage attribution subject +// keys contain the subject key, and customers whose own key is the subject key. type fakeCustomerService struct { customer.Service - customerIDBySubjectKey map[string]string + customerIDBySubjectKey map[string]string + customerIDByCustomerKey map[string]string } func (f *fakeCustomerService) ListCustomers(_ context.Context, input customer.ListCustomersInput) (pagination.Result[customer.Customer], error) { var items []customer.Customer - // Only the usage-attribution lookup resolves customers in this fake; the - // customer-key lookup returns no matches. if input.UsageAttributionSubjectKey != nil && input.UsageAttributionSubjectKey.In != nil { for _, key := range *input.UsageAttributionSubjectKey.In { if customerID, ok := f.customerIDBySubjectKey[key]; ok { @@ -70,6 +70,17 @@ func (f *fakeCustomerService) ListCustomers(_ context.Context, input customer.Li } } + if input.Key != nil && input.Key.In != nil { + for _, key := range *input.Key.In { + if customerID, ok := f.customerIDByCustomerKey[key]; ok { + items = append(items, customer.Customer{ + ManagedResource: models.ManagedResource{ID: customerID}, + Key: lo.ToPtr(key), + }) + } + } + } + return pagination.Result[customer.Customer]{Items: items, TotalCount: len(items)}, nil } @@ -106,6 +117,30 @@ func TestListSubjects(t *testing.T) { require.Equal(t, 1, connector.calls) }) + t.Run("AttributedByCustomerKey", func(t *testing.T) { + // given: + // - a customer attributed by its own key, with no usage attribution subject keys + // when: + // - listing attributed subjects + // then: + // - the subject matching the customer key is attributed + connector := &fakeStreamingConnector{keys: []string{"s1", "s2"}} + a := &adapter{ + streamingConnector: connector, + customerService: &fakeCustomerService{customerIDByCustomerKey: map[string]string{"s2": "customer-2"}}, + } + + result, err := a.ListSubjects(t.Context(), meterevent.ListSubjectsParams{ + Namespace: "ns", + Limit: lo.ToPtr(10), + Attributed: lo.ToPtr(true), + }) + require.NoError(t, err) + + require.Equal(t, []meterevent.Subject{{Key: "s2"}}, result.Items) + require.Nil(t, result.NextCursor) + }) + t.Run("FullPageEmitsNextCursor", func(t *testing.T) { a, _ := newAdapter([]string{"s1", "s2", "s3"}, nil) diff --git a/openmeter/streaming/clickhouse/connector.go b/openmeter/streaming/clickhouse/connector.go index af9b70ba34..c72eaa09a6 100644 --- a/openmeter/streaming/clickhouse/connector.go +++ b/openmeter/streaming/clickhouse/connector.go @@ -606,6 +606,7 @@ func (c *Connector) listSubjectsV2(ctx context.Context, params streaming.ListSub Database: c.config.Database, EventsTableName: c.config.EventsTableName, Params: params, + QuerySettings: c.config.MeterQuerySettings, } sql, args := query.toSQL() diff --git a/openmeter/streaming/clickhouse/subject_query.go b/openmeter/streaming/clickhouse/subject_query.go index 95554ccac1..64415e6bbe 100644 --- a/openmeter/streaming/clickhouse/subject_query.go +++ b/openmeter/streaming/clickhouse/subject_query.go @@ -2,6 +2,7 @@ package clickhouse import ( "fmt" + "strings" "time" "github.com/huandu/go-sqlbuilder" @@ -81,6 +82,7 @@ type listSubjectsV2Query struct { Database string EventsTableName string Params streaming.ListSubjectsV2Params + QuerySettings map[string]string } // toSQL builds the subjects listing query. It uses GROUP BY instead of @@ -93,6 +95,11 @@ func (d listSubjectsV2Query) toSQL() (string, []interface{}) { query.Select("subject") query.From(tableName) query.Where(query.Equal("namespace", d.Params.Namespace)) + // Empty subjects cannot be ingested through the API, but rows written by + // direct producers would break the attributed filter (empty values are + // rejected by pkg/filter) and produce cursors with an empty ID, so they + // are excluded at the source. + query.Where(query.NotEqual("subject", "")) if d.Params.Key != nil { expr := d.Params.Key.SelectWhereExpr("subject", query) @@ -110,5 +117,17 @@ func (d listSubjectsV2Query) toSQL() (string, []interface{}) { query.OrderBy("namespace", "subject") query.Limit(lo.FromPtrOr(d.Params.Limit, listSubjectsV2DefaultLimit)) + // Guard the aggregation cost: without the subjects projection this query + // scans the namespace's events, so the configured query settings (e.g. + // max_execution_time) must bound it server-side. + var settings []string + for key, value := range d.QuerySettings { + settings = append(settings, fmt.Sprintf("%s = %s", key, value)) + } + + if len(settings) > 0 { + query.SQL(fmt.Sprintf("SETTINGS %s", strings.Join(settings, ", "))) + } + return query.Build() } diff --git a/openmeter/streaming/clickhouse/subject_query_test.go b/openmeter/streaming/clickhouse/subject_query_test.go index 7b9f675c20..057a81dbb3 100644 --- a/openmeter/streaming/clickhouse/subject_query_test.go +++ b/openmeter/streaming/clickhouse/subject_query_test.go @@ -121,8 +121,8 @@ func TestListSubjectsV2(t *testing.T) { Namespace: "my_namespace", }, }, - wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", - wantArgs: []interface{}{"my_namespace", 100}, + wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND subject <> ? GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", + wantArgs: []interface{}{"my_namespace", "", 100}, }, { name: "query with key filter", @@ -134,8 +134,8 @@ func TestListSubjectsV2(t *testing.T) { Key: &filter.FilterString{Ilike: lo.ToPtr("%customer%")}, }, }, - wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND LOWER(subject) LIKE LOWER(?) GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", - wantArgs: []interface{}{"my_namespace", "%customer%", 100}, + wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND subject <> ? AND LOWER(subject) LIKE LOWER(?) GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", + wantArgs: []interface{}{"my_namespace", "", "%customer%", 100}, }, { name: "query with cursor and limit", @@ -148,8 +148,21 @@ func TestListSubjectsV2(t *testing.T) { Limit: lo.ToPtr(10), }, }, - wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND subject > ? GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", - wantArgs: []interface{}{"my_namespace", "customer-1", 10}, + wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND subject <> ? AND subject > ? GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ?", + wantArgs: []interface{}{"my_namespace", "", "customer-1", 10}, + }, + { + name: "query with settings", + query: listSubjectsV2Query{ + Database: "openmeter", + EventsTableName: "om_events", + Params: streaming.ListSubjectsV2Params{ + Namespace: "my_namespace", + }, + QuerySettings: map[string]string{"max_execution_time": "60"}, + }, + wantSQL: "SELECT subject FROM openmeter.om_events WHERE namespace = ? AND subject <> ? GROUP BY namespace, subject ORDER BY namespace, subject LIMIT ? SETTINGS max_execution_time = 60", + wantArgs: []interface{}{"my_namespace", "", 100}, }, }