Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
27 changes: 27 additions & 0 deletions docs/content/getting-started/perform-list-objects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
SupportedLanguage,
languageLabelMap,
ListObjectsRequestViewer,
StreamedListObjectsRequestViewer,
DocumentationNotice,
ProductConcept,
ProductName,
Expand Down Expand Up @@ -182,6 +183,27 @@ The result `document:otherdoc` and `document:planning` are the document objects
The performance characteristics of the ListObjects endpoint vary drastically depending on the model complexity, number of tuples, and the relations it needs to evaluate. Relations with 'and' or 'but not' are more expensive to evaluate than relations with 'or'.
:::

## Streamed List Objects

The Streamed ListObjects API is similar to the ListObjects API, with two key differences:

1. **Streaming Response**: Instead of collecting all objects before returning a response, it streams them to the client as they are collected.
2. **No Result Limit**: The number of results returned is only limited by the execution timeout specified in the flag `OPENFGA_LIST_OBJECTS_DEADLINE`, not by a fixed limit.

:::info
The streaming functionality is currently available in the **Node.js SDK**, **Go SDK**, **.NET SDK**, **Python SDK**, and **Java SDK**.
:::

### Using Streamed List Objects

<StreamedListObjectsRequestViewer
user="user:anne"
relation="reader"
objectType="document"
expectedResults={['document:otherdoc', 'document:planning']}
skipSetup={true}
/>

## Related Sections

<RelatedSection
Expand All @@ -192,5 +214,10 @@ The performance characteristics of the ListObjects endpoint vary drastically dep
description: 'Read the List Objects API documentation and see how it works.',
link: '/api/service#Relationship%20Queries/ListObjects',
},
{
title: '{ProductName} Streamed List Objects API',
description: 'Read the Streamed List Objects API documentation.',
link: '/api/service#Relationship%20Queries/StreamedListObjects',
},
]}
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { getFilteredAllowedLangs, SupportedLanguage } from './SupportedLanguage';
import { defaultOperationsViewer } from './DefaultTabbedViewer';
import assertNever from 'assert-never/index';

interface StreamedListObjectsRequestViewerOpts {
user: string;
relation: string;
objectType: string;
expectedResults: string[];
skipSetup?: boolean;
allowedLanguages?: SupportedLanguage[];
}

function streamedListObjectsRequestViewer(lang: SupportedLanguage, opts: StreamedListObjectsRequestViewerOpts): string {
const { user, relation, objectType, expectedResults } = opts;

switch (lang) {
case SupportedLanguage.PLAYGROUND:
return `# Note: Streamed List Objects is not currently supported on the playground`;
case SupportedLanguage.CLI:
return `# Note: Streamed List Objects is not currently supported in the CLI`;
case SupportedLanguage.CURL:
return `curl -X POST $FGA_API_URL/stores/$FGA_STORE_ID/streamed-list-objects \\
-H "Authorization: Bearer $FGA_API_TOKEN" \\ # Not needed if service does not require authorization
-H "content-type: application/json" \\
-d '{
"type": "${objectType}",
"relation": "${relation}",
"user":"${user}"
}'


# Response:
${expectedResults.map((r) => `{"result":{"object":"${r}"}}`).join('\n')}`;
case SupportedLanguage.JS_SDK:
return `const objects = [];
for await (const response of fgaClient.streamedListObjects(
{ user: "${user}", relation: "${relation}", type: "${objectType}" }
)) {
objects.push(response.object);
}
// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`;
case SupportedLanguage.DOTNET_SDK:
return `var objects = new List<string>();
await foreach (var response in fgaClient.StreamedListObjects(
new ClientListObjectsRequest {
User = "${user}",
Relation = "${relation}",
Type = "${objectType}"
})) {
objects.Add(response.Object);
}
// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`;
case SupportedLanguage.PYTHON_SDK:
return `objects = []
async for response in fga_client.streamed_list_objects(
ClientListObjectsRequest(
user="${user}",
relation="${relation}",
type="${objectType}"
)
):
objects.append(response.object)
# objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`;
case SupportedLanguage.GO_SDK:
return `objects := []string{}
err := fgaClient.StreamedListObjects(context.Background()).
Body(client.ClientListObjectsRequest{
User: "${user}",
Relation: "${relation}",
Type: "${objectType}",
}).
Execute(func(response *client.ClientStreamedListObjectsResponse) error {
objects = append(objects, response.Object)
return nil
})
// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`;
case SupportedLanguage.JAVA_SDK:
return `var objects = new ArrayList<String>();
var request = new ClientListObjectsRequest()
.user("${user}")
.relation("${relation}")
.type("${objectType}");

fgaClient.streamedListObjects(request, new ClientStreamedListObjectsOptions(), response -> {
objects.add(response.getObject());
}).get();
// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`;
case SupportedLanguage.RPC:
return `# Note: Use CURL or SDK for streaming examples`;
default:
return assertNever(lang);
}
}

export function StreamedListObjectsRequestViewer(opts: StreamedListObjectsRequestViewerOpts): JSX.Element {
const defaultLangs = [
SupportedLanguage.JS_SDK,
SupportedLanguage.GO_SDK,
SupportedLanguage.DOTNET_SDK,
SupportedLanguage.PYTHON_SDK,
SupportedLanguage.JAVA_SDK,
];
const allowedLanguages = getFilteredAllowedLangs(opts.allowedLanguages, defaultLangs);
return defaultOperationsViewer(allowedLanguages, opts, streamedListObjectsRequestViewer);
}
1 change: 1 addition & 0 deletions src/components/Docs/SnippetViewer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export * from './ReadChangesRequestViewer';
export * from './ReadRequestViewer';
export { SdkSetupHeader } from './SdkSetup';
export { SupportedLanguage, languageLabelMap } from './SupportedLanguage';
export * from './StreamedListObjectsRequestViewer';
export * from './WriteRequestViewer';
export * from './WriteAuthzModelViewer';
Loading