Skip to content

Commit

Permalink
Add final method call to request context header (#478)
Browse files Browse the repository at this point in the history
* Add final method call to all request-sending methods except asyncIter

* Mark asyncIter-originated fetchPage calls

* Fix asyncIter to actually fetch next pages

* Add changeset

* Fix runAssignEmployeeToVentureTest

* Stop exposing calledByAsyncIter argument in fetchPage

* Fix semantic merge conflict with queries PR

* Add final method call to applyQuery

* Make return type of augment fn a Partial<RequestContext>

* Add rationale for augment fn in comment
  • Loading branch information
bryantpark04 authored Jul 19, 2024
1 parent 6a91177 commit dec005b
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 40 deletions.
6 changes: 6 additions & 0 deletions .changeset/strange-mails-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@osdk/client.api": patch
"@osdk/client": patch
---

Add final method call to request context header
5 changes: 5 additions & 0 deletions packages/client/src/MinimalClientContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@ declare const tag: unique symbol;

export type ClientCacheKey = {} & { readonly [tag]: void };

export type RequestContext = {
finalMethodCall?: string;
};

export interface MinimalClient extends SharedClientContext {
ontologyRid: string | Promise<string>;
ontologyProvider: OntologyProvider;
logger?: Logger;
objectSetFactory: ObjectSetFactory<any, any>;
clientCacheKey: ClientCacheKey;
requestContext: RequestContext;
}

export type MinimalClientParams = {
Expand Down
11 changes: 8 additions & 3 deletions packages/client/src/actions/applyAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import type {
import type { DataValue } from "@osdk/internal.foundry";
import { Ontologies, OntologiesV2 } from "@osdk/internal.foundry";
import type { MinimalClient } from "../MinimalClientContext.js";
import { addUserAgent } from "../util/addUserAgent.js";
import { addUserAgentAndRequestContextHeaders } from "../util/addUserAgentAndRequestContextHeaders.js";
import { augmentRequestContext } from "../util/augmentRequestContext.js";
import { toDataValue } from "../util/toDataValue.js";
import { ActionValidationError } from "./ActionValidationError.js";

Expand All @@ -45,9 +46,13 @@ export async function applyAction<
): Promise<
ActionReturnTypeForOptions<Op>
> {
const clientWithHeaders = addUserAgentAndRequestContextHeaders(
augmentRequestContext(client, _ => ({ finalMethodCall: "applyAction" })),
action,
);
if (Array.isArray(parameters)) {
const response = await OntologiesV2.Actions.applyActionBatchV2(
addUserAgent(client, action),
clientWithHeaders,
await client.ontologyRid,
action.apiName,
{
Expand All @@ -65,7 +70,7 @@ export async function applyAction<
: undefined) as ActionReturnTypeForOptions<Op>;
} else {
const response = await OntologiesV2.Actions.applyActionV2(
addUserAgent(client, action),
clientWithHeaders,
await client.ontologyRid,
action.apiName,
{
Expand Down
1 change: 1 addition & 0 deletions packages/client/src/createMinimalClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function createMinimalClient(
ontologyRid: metadata.ontologyRid,
logger: options.logger,
clientCacheKey: {} as ClientCacheKey,
requestContext: {},
} satisfies Omit<
MinimalClient,
"ontologyProvider"
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/object/aggregate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { modernToLegacyAggregationClause } from "../internal/conversions/modernT
import { modernToLegacyGroupByClause } from "../internal/conversions/modernToLegacyGroupByClause.js";
import { modernToLegacyWhereClause } from "../internal/conversions/modernToLegacyWhereClause.js";
import type { MinimalClient } from "../MinimalClientContext.js";
import { addUserAgent } from "../util/addUserAgent.js";
import { addUserAgentAndRequestContextHeaders } from "../util/addUserAgentAndRequestContextHeaders.js";
import type { ArrayElement } from "../util/ArrayElement.js";

/** @deprecated use `aggregate` */
Expand Down Expand Up @@ -79,7 +79,7 @@ export async function aggregate<
body.where = modernToLegacyWhereClause(req.$where);
}
const result = await OntologiesV2.OntologyObjectSets.aggregateObjectSetV2(
addUserAgent(clientCtx, objectType),
addUserAgentAndRequestContextHeaders(clientCtx, objectType),
await clientCtx.ontologyRid,
{
objectSet,
Expand Down
20 changes: 15 additions & 5 deletions packages/client/src/object/fetchPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import type {
} from "@osdk/internal.foundry";
import { OntologiesV2 } from "@osdk/internal.foundry";
import type { MinimalClient } from "../MinimalClientContext.js";
import { addUserAgent } from "../util/addUserAgent.js";
import { addUserAgentAndRequestContextHeaders } from "../util/addUserAgentAndRequestContextHeaders.js";
import { convertWireToOsdkObjects } from "./convertWireToOsdkObjects.js";

export function augment<
Expand Down Expand Up @@ -95,7 +95,7 @@ async function fetchInterfacePage<
objectSet: ObjectSet,
): Promise<FetchPageResult<Q, L, R, S>> {
const result = await OntologiesV2.OntologyObjectsV2.searchObjectsForInterface(
addUserAgent(client, interfaceType),
addUserAgentAndRequestContextHeaders(client, interfaceType),
await client.ontologyRid,
interfaceType.apiName,
applyFetchArgs<SearchObjectsForInterfaceRequest>(args, {
Expand Down Expand Up @@ -131,9 +131,19 @@ export async function fetchPageInternal<
args: FetchPageArgs<Q, L, R, A, S> = {},
): Promise<FetchPageResult<Q, L, R, S>> {
if (objectType.type === "interface") {
return await fetchInterfacePage(client, objectType, args, objectSet) as any; // fixme
return await fetchInterfacePage(
client,
objectType,
args,
objectSet,
) as any; // fixme
} else {
return await fetchObjectPage(client, objectType, args, objectSet) as any; // fixme
return await fetchObjectPage(
client,
objectType,
args,
objectSet,
) as any; // fixme
}
}

Expand Down Expand Up @@ -237,7 +247,7 @@ export async function fetchObjectPage<
objectSet: ObjectSet,
): Promise<FetchPageResult<Q, L, R, S>> {
const r = await OntologiesV2.OntologyObjectSets.loadObjectSetV2(
addUserAgent(client, objectType),
addUserAgentAndRequestContextHeaders(client, objectType),
await client.ontologyRid,
applyFetchArgs<LoadObjectSetRequestV2>(args, {
objectSet,
Expand Down
31 changes: 24 additions & 7 deletions packages/client/src/objectSet/createObjectSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ import type { ObjectSet as WireObjectSet } from "@osdk/internal.foundry";
import { modernToLegacyWhereClause } from "../internal/conversions/modernToLegacyWhereClause.js";
import type { MinimalClient } from "../MinimalClientContext.js";
import { aggregate } from "../object/aggregate.js";
import { convertWireToOsdkObjects } from "../object/convertWireToOsdkObjects.js";
import {
fetchPageInternal,
fetchPageWithErrorsInternal,
} from "../object/fetchPage.js";
import { fetchSingle, fetchSingleWithErrors } from "../object/fetchSingle.js";
import { augmentRequestContext } from "../util/augmentRequestContext.js";
import { isWireObjectSet } from "../util/WireObjectSet.js";

function isObjectTypeDefinition(
Expand Down Expand Up @@ -77,21 +77,24 @@ export function createObjectSet<Q extends ObjectOrInterfaceDefinition>(
const base: Omit<ObjectSet<Q>, keyof BaseObjectSet<Q>> = {
aggregate: (aggregate<Q, any>).bind(
globalThis,
clientCtx,
augmentRequestContext(clientCtx, _ => ({ finalMethodCall: "aggregate" })),
objectType,
objectSet,
),

fetchPage: fetchPageInternal.bind(
globalThis,
clientCtx,
augmentRequestContext(clientCtx, _ => ({ finalMethodCall: "fetchPage" })),
objectType,
objectSet,
) as ObjectSet<Q>["fetchPage"],

fetchPageWithErrors: fetchPageWithErrorsInternal.bind(
globalThis,
clientCtx,
augmentRequestContext(
clientCtx,
_ => ({ finalMethodCall: "fetchPageWithErrors" }),
),
objectType,
objectSet,
) as ObjectSet<Q>["fetchPageWithErrors"],
Expand Down Expand Up @@ -148,7 +151,15 @@ export function createObjectSet<Q extends ObjectOrInterfaceDefinition>(
ObjectOrInterfacePropertyKeysFrom2<Q>,
boolean,
"throw"
> = await base.fetchPage({ $nextPageToken });
> = await fetchPageInternal(
augmentRequestContext(
clientCtx,
_ => ({ finalMethodCall: "asyncIter" }),
),
objectType,
objectSet,
{ $nextPageToken },
);
$nextPageToken = result.nextPageToken;

for (const obj of result.data) {
Expand All @@ -175,7 +186,10 @@ export function createObjectSet<Q extends ObjectOrInterfaceDefinition>(
};

return await fetchSingle(
clientCtx,
augmentRequestContext(
clientCtx,
_ => ({ finalMethodCall: "fetchOne" }),
),
objectType,
options,
withPk,
Expand All @@ -201,7 +215,10 @@ export function createObjectSet<Q extends ObjectOrInterfaceDefinition>(
};

return await fetchSingleWithErrors(
clientCtx,
augmentRequestContext(
clientCtx,
_ => ({ finalMethodCall: "fetchOneWithErrors" }),
),
objectType,
options,
withPk,
Expand Down
8 changes: 6 additions & 2 deletions packages/client/src/queries/applyQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ import { OntologiesV2 } from "@osdk/internal.foundry";
import { createAttachmentFromRid } from "../createAttachmentFromRid.js";
import type { MinimalClient } from "../MinimalClientContext.js";
import { createObjectSet } from "../objectSet/createObjectSet.js";
import { addUserAgent } from "../util/addUserAgent.js";
import { addUserAgentAndRequestContextHeaders } from "../util/addUserAgentAndRequestContextHeaders.js";
import { augmentRequestContext } from "../util/augmentRequestContext.js";
import { toDataValue } from "../util/toDataValue.js";
import { toDataValueQueries } from "../util/toDataValueQueries.js";

Expand All @@ -53,7 +54,10 @@ export async function applyQuery<
QueryReturnType<QD["output"]>
> {
const response = await OntologiesV2.QueryTypes.executeQueryV2(
addUserAgent(client, query),
addUserAgentAndRequestContextHeaders(
augmentRequestContext(client, _ => ({ finalMethodCall: "applyQuery" })),
query,
),
await client.ontologyRid,
query.apiName,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,26 @@ import type { ObjectOrInterfaceDefinition } from "@osdk/api";
import { createFetchHeaderMutator } from "@osdk/shared.net.fetch";
import type { MinimalClient } from "../MinimalClientContext.js";

export function addUserAgent(
export const addUserAgentAndRequestContextHeaders = (
client: MinimalClient,
withMetadata: Pick<ObjectOrInterfaceDefinition, "osdkMetadata">,
): MinimalClient {
if (withMetadata.osdkMetadata) {
return {
...client,
fetch: createFetchHeaderMutator(
client.fetch,
(headers) => {
headers.set(
"Fetch-User-Agent",
withMetadata.osdkMetadata!.extraUserAgent,
);
return headers;
},
),
};
}
return client;
}
): MinimalClient => ({
...client,
fetch: createFetchHeaderMutator(
client.fetch,
(headers) => {
headers.set(
"X-OSDK-Request-Context",
JSON.stringify(client.requestContext),
);

if (withMetadata.osdkMetadata) {
headers.set(
"Fetch-User-Agent",
withMetadata.osdkMetadata.extraUserAgent,
);
}
return headers;
},
),
});
57 changes: 57 additions & 0 deletions packages/client/src/util/augmentRequestContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2024 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { MinimalClient, RequestContext } from "../MinimalClientContext.js";

/**
Returns a client with its `requestContext` merged with the result of applying
`augment` to its `requestContext`.
The second argument is an `Partial<RequestContext>`-returning `augment` function
instead of a `RequestContext` object to make referencing the current request
context easier. For example, modifying the `fetchPage` function to add its name
to the object set's called method chain could look like:
```
augmentRequestContext(
clientContext,
ctx => ({ methodChain: [...ctx.methodChain, "fetchPage"] })
)
```
or
```
augmentRequestContext(
clientContext,
({ methodChain }) => ({ methodChain: [...methodChain, "fetchPage"] })
)
```
instead of
```
augmentRequestContext(
clientContext,
{ methodChain: [...clientContext.requestContext.methodChain, "fetchPage"] }
)
```
*/
export const augmentRequestContext = (
client: MinimalClient,
augment: (ctx: RequestContext) => Partial<RequestContext>,
): MinimalClient => ({
...client,
requestContext: {
...client.requestContext,
...augment(client.requestContext),
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export async function runAssignEmployeeToVentureTest() {
const { data: [venture] } = await client(Venture).fetchPage();

const r = await client(assignEmployee1).applyAction({
"employee-1": emp,
"venture-1": venture,
"employee-1": emp.id,
"venture-1": venture.ventureId,
}, {
$validateOnly: true,
});
Expand Down

0 comments on commit dec005b

Please sign in to comment.