Skip to content

Commit 5b77add

Browse files
Flo4604mcstepp
authored andcommitted
perf: fix n+1 (#4484)
1 parent f32045f commit 5b77add

File tree

4 files changed

+145
-53
lines changed

4 files changed

+145
-53
lines changed

go/apps/api/routes/v2_identities_list_identities/handler.go

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package handler
22

33
import (
44
"context"
5-
"database/sql"
6-
"errors"
75
"net/http"
86

97
"github.com/unkeyed/unkey/go/apps/api/openapi"
@@ -100,18 +98,19 @@ func (h *Handler) Handle(ctx context.Context, s *zen.Session) error {
10098
}
10199
}
102100

103-
// Process the results and get ratelimits for each identity
101+
// Process the results
104102
data := make([]openapi.Identity, 0, len(identities))
105103
for _, identity := range identities {
106-
// Fetch ratelimits for this identity
107-
ratelimits, err := db.Query.ListIdentityRatelimits(ctx, h.DB.RO(), sql.NullString{Valid: true, String: identity.ID})
108-
if err != nil && !errors.Is(err, sql.ErrNoRows) {
109-
return fault.Wrap(err,
110-
fault.Internal("unable to fetch ratelimits"), fault.Public("We're unable to retrieve ratelimits for the identities."),
104+
// Unmarshal ratelimits from JSON
105+
ratelimits, err := db.UnmarshalNullableJSONTo[[]db.RatelimitInfo](identity.Ratelimits)
106+
if err != nil {
107+
h.Logger.Error("failed to unmarshal identity ratelimits",
108+
"identityId", identity.ID,
109+
"error", err,
111110
)
112111
}
113112

114-
// Format ratelimits
113+
// Convert to openapi response format
115114
formattedRatelimits := make([]openapi.RatelimitResponse, 0, len(ratelimits))
116115
for _, r := range ratelimits {
117116
formattedRatelimits = append(formattedRatelimits, openapi.RatelimitResponse{
@@ -123,30 +122,21 @@ func (h *Handler) Handle(ctx context.Context, s *zen.Session) error {
123122
})
124123
}
125124

126-
// Create a new identity with its ratelimits
127-
newIdentity := openapi.Identity{
128-
Id: identity.ID,
129-
ExternalId: identity.ExternalID,
130-
Ratelimits: nil,
131-
Meta: nil,
132-
}
133-
134-
newIdentity.Ratelimits = formattedRatelimits
135-
136-
// Add metadata if available
125+
// Unmarshal metadata
137126
metaMap, err := db.UnmarshalNullableJSONTo[map[string]any](identity.Meta)
138-
newIdentity.Meta = metaMap
139-
140127
if err != nil {
141128
h.Logger.Error("failed to unmarshal identity meta",
142129
"identityId", identity.ID,
143130
"error", err,
144131
)
145-
// Continue with empty meta
146132
}
147133

148-
// Append the identity to the results
149-
data = append(data, newIdentity)
134+
data = append(data, openapi.Identity{
135+
Id: identity.ID,
136+
ExternalId: identity.ExternalID,
137+
Ratelimits: formattedRatelimits,
138+
Meta: metaMap,
139+
})
150140
}
151141

152142
response := Response{

go/pkg/db/identity_list.sql_generated.go

Lines changed: 73 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/pkg/db/querier_generated.go

Lines changed: 29 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
11
-- name: ListIdentities :many
2-
SELECT *
3-
FROM identities
4-
WHERE workspace_id = sqlc.arg(workspace_id)
5-
AND deleted = sqlc.arg(deleted)
6-
AND id >= sqlc.arg(id_cursor)
7-
ORDER BY id ASC
2+
SELECT
3+
i.id,
4+
i.external_id,
5+
i.workspace_id,
6+
i.environment,
7+
i.meta,
8+
i.deleted,
9+
i.created_at,
10+
i.updated_at,
11+
COALESCE(
12+
(SELECT JSON_ARRAYAGG(
13+
JSON_OBJECT(
14+
'id', r.id,
15+
'name', r.name,
16+
'limit', r.`limit`,
17+
'duration', r.duration,
18+
'auto_apply', r.auto_apply = 1
19+
)
20+
)
21+
FROM ratelimits r
22+
WHERE r.identity_id = i.id),
23+
JSON_ARRAY()
24+
) as ratelimits
25+
FROM identities i
26+
WHERE i.workspace_id = sqlc.arg(workspace_id)
27+
AND i.deleted = sqlc.arg(deleted)
28+
AND i.id >= sqlc.arg(id_cursor)
29+
ORDER BY i.id ASC
830
LIMIT ?

0 commit comments

Comments
 (0)