Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 48 additions & 19 deletions connect-go/gen/proto/wg/cosmo/platform/v1/platform.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions connect/src/wg/cosmo/platform/v1/platform_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13892,6 +13892,16 @@ export class GetAllOverridesRequest extends Message<GetAllOverridesRequest> {
*/
namespace = "";

/**
* @generated from field: int32 limit = 3;
*/
limit = 0;

/**
* @generated from field: int32 offset = 4;
*/
offset = 0;

constructor(data?: PartialMessage<GetAllOverridesRequest>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -13902,6 +13912,8 @@ export class GetAllOverridesRequest extends Message<GetAllOverridesRequest> {
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "graph_name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "namespace", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "limit", kind: "scalar", T: 5 /* ScalarType.INT32 */ },
{ no: 4, name: "offset", kind: "scalar", T: 5 /* ScalarType.INT32 */ },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetAllOverridesRequest {
Expand Down Expand Up @@ -13935,6 +13947,11 @@ export class GetAllOverridesResponse extends Message<GetAllOverridesResponse> {
*/
overrides: GetAllOverridesResponse_Override[] = [];

/**
* @generated from field: int32 total_count = 3;
*/
totalCount = 0;

constructor(data?: PartialMessage<GetAllOverridesResponse>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -13945,6 +13962,7 @@ export class GetAllOverridesResponse extends Message<GetAllOverridesResponse> {
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "response", kind: "message", T: Response },
{ no: 2, name: "overrides", kind: "message", T: GetAllOverridesResponse_Override, repeated: true },
{ no: 3, name: "total_count", kind: "scalar", T: 5 /* ScalarType.INT32 */ },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetAllOverridesResponse {
Expand Down
12 changes: 10 additions & 2 deletions controlplane/src/core/bufservices/check/getAllOverrides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { FederatedGraphRepository } from '../../repositories/FederatedGraphRepository.js';
import { OperationsRepository } from '../../repositories/OperationsRepository.js';
import type { RouterOptions } from '../../routes.js';
import { enrichLogger, getLogger, handleError } from '../../util.js';
import { clamp, enrichLogger, getLogger, handleError } from '../../util.js';
import { UnauthorizedError } from '../../errors/errors.js';

export function getAllOverrides(
Expand All @@ -33,6 +33,7 @@ export function getAllOverrides(
details: 'Requested graph does not exist',
},
overrides: [],
totalCount: 0,
};
}

Expand All @@ -42,15 +43,22 @@ export function getAllOverrides(

const operationsRepo = new OperationsRepository(opts.db, graph.id);

const overrides = await operationsRepo.getConsolidatedOverridesView({
// default to 10 if no limit is provided
const limit = clamp(req.limit || 10, 1, 50);
const offset = clamp(req.offset || 0, 0, 500_000);
Comment thread
comatory marked this conversation as resolved.
Outdated

const { overrides, totalCount } = await operationsRepo.getConsolidatedOverridesView({
namespaceId: graph.namespaceId,
limit,
offset,
});

return {
response: {
code: EnumStatusCode.OK,
},
overrides,
totalCount,
};
});
}
24 changes: 20 additions & 4 deletions controlplane/src/core/repositories/OperationsRepository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OverrideChange } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb';
import { aliasedTable, and, asc, desc, eq, isNull, sql } from 'drizzle-orm';
import { aliasedTable, and, asc, count, desc, eq, isNull, sql } from 'drizzle-orm';
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
import { PlainMessage } from '@bufbuild/protobuf';
import { DBSchemaChangeType } from '../../db/models.js';
Expand Down Expand Up @@ -443,7 +443,7 @@ export class OperationsRepository {
};
}

public getConsolidatedOverridesView(data: { namespaceId: string }) {
public async getConsolidatedOverridesView(data: { namespaceId: string; limit: number; offset: number }) {
const change = this.db
.select({
hash: schema.operationChangeOverrides.hash,
Expand Down Expand Up @@ -484,7 +484,7 @@ export class OperationsRepository {
// We need to retrieve a consolidated view of overrides from both tables.
// There is no guarantee that an entry for hash exists in both.

return this.db
const baseQuery = this.db
.select({
hash: sql<string>`coalesce(${change.hash}, ${ignore.hash})`,
name: sql<string>`coalesce(${change.name}, ${ignore.name})`,
Expand All @@ -497,7 +497,23 @@ export class OperationsRepository {
.from(change)
.fullJoin(ignore, and(eq(change.hash, ignore.hash), eq(change.namespaceId, ignore.namespaceId)))
.leftJoin(changeCounts, and(eq(change.hash, changeCounts.hash), eq(change.namespaceId, changeCounts.namespaceId)))
.orderBy(({ name, hash }) => [asc(name), asc(hash)]);
.orderBy(({ name, hash }) => [asc(name), asc(hash)])
.limit(data.limit)
.offset(data.offset);

const countQuery = this.db
.select({
count: count(),
})
.from(change)
.fullJoin(ignore, and(eq(change.hash, ignore.hash), eq(change.namespaceId, ignore.namespaceId)));

const [overrides, countResult] = await Promise.all([baseQuery, countQuery]);

return {
overrides,
totalCount: countResult[0]?.count ?? 0,
};
}

private static createPersistedOperationDTO({
Expand Down
80 changes: 80 additions & 0 deletions controlplane/test/override.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,84 @@ describe('Overrides', (ctx) => {
expect(overridesRes.overrides[1].changesOverrideCount).toBe(0);
expect(overridesRes.overrides[1].hasIgnoreAllOverride).toBe(true);
});

test('Should paginate overrides with limit and offset', async (testContext) => {
const { client, server } = await SetupTest({ dbname });
testContext.onTestFinished(() => server.close());

const fedGraphName = genID('fedGraph');
const label = genUniqueLabel();

const createFedGraphRes = await client.createFederatedGraph({
name: fedGraphName,
namespace: 'default',
routingUrl: 'http://localhost:8081',
labelMatchers: [joinLabel(label)],
});
expect(createFedGraphRes.response?.code).toBe(EnumStatusCode.OK);

const graphRes = await client.getFederatedGraphByName({
name: fedGraphName,
namespace: 'default',
});
expect(graphRes.response?.code).toBe(EnumStatusCode.OK);

// Create 3 overrides
for (let i = 1; i <= 3; i++) {
const res = await client.createOperationOverrides({
graphName: graphRes.graph?.name,
namespace: graphRes.graph?.namespace,
operationHash: `hash${i}`,
operationName: `op${i}`,
changes: [
{
changeType: 'FIELD_TYPE_CHANGED',
path: `A.field${i}`,
},
],
});
expect(res.response?.code).toBe(EnumStatusCode.OK);
}

// Fetch all without pagination params — should return all 3
const allRes = await client.getAllOverrides({
graphName: graphRes.graph?.name,
namespace: graphRes.graph?.namespace,
});
expect(allRes.response?.code).toBe(EnumStatusCode.OK);
expect(allRes.totalCount).toBe(3);

// Fetch first page with limit 2
const page1 = await client.getAllOverrides({
graphName: graphRes.graph?.name,
namespace: graphRes.graph?.namespace,
limit: 2,
offset: 0,
});
expect(page1.response?.code).toBe(EnumStatusCode.OK);
expect(page1.overrides.length).toBe(2);
expect(page1.totalCount).toBe(3);

// Fetch second page with limit 2, offset 2
const page2 = await client.getAllOverrides({
graphName: graphRes.graph?.name,
namespace: graphRes.graph?.namespace,
limit: 2,
offset: 2,
});
expect(page2.response?.code).toBe(EnumStatusCode.OK);
expect(page2.overrides.length).toBe(1);
expect(page2.totalCount).toBe(3);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Fetch with offset beyond total — should return empty but correct totalCount
const page3 = await client.getAllOverrides({
graphName: graphRes.graph?.name,
namespace: graphRes.graph?.namespace,
limit: 10,
offset: 10,
});
expect(page3.response?.code).toBe(EnumStatusCode.OK);
expect(page3.overrides.length).toBe(0);
expect(page3.totalCount).toBe(3);
});
});
3 changes: 3 additions & 0 deletions proto/wg/cosmo/platform/v1/platform.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1801,6 +1801,8 @@ message GetOperationOverridesResponse {
message GetAllOverridesRequest {
string graph_name = 1;
string namespace = 2;
int32 limit = 3;
int32 offset = 4;
}

message GetAllOverridesResponse {
Expand All @@ -1814,6 +1816,7 @@ message GetAllOverridesResponse {

Response response = 1;
repeated Override overrides = 2;
int32 total_count = 3;
}

message IsGitHubAppInstalledRequest {
Expand Down
Loading
Loading