Skip to content

Commit

Permalink
Adds pagination to apps view page
Browse files Browse the repository at this point in the history
This is not perfect -- but it'll do. The caveat is that parent/child
pointers aren't always found -- we need to add that to the API.
  • Loading branch information
elijahbenizzy committed Aug 28, 2024
1 parent f51fdcf commit ff73f02
Show file tree
Hide file tree
Showing 13 changed files with 369 additions and 69 deletions.
6 changes: 4 additions & 2 deletions burr/cli/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ def build_and_publish(prod: bool, no_wipe_dist: bool):
default="burr/tracking/server/demo_data",
)
@click.option("--unique-app-names", help="Use unique app names", is_flag=True)
def generate_demo_data(s3_bucket, data_dir, unique_app_names: bool):
@click.option("--no-clear-current-data", help="Don't clear current data", is_flag=True)
def generate_demo_data(s3_bucket, data_dir, unique_app_names: bool, no_clear_current_data: bool):
_telemetry_if_enabled("generate_demo_data")
git_root = _get_git_root()
# We need to add the examples directory to the path so we have all the imports
Expand All @@ -236,7 +237,8 @@ def generate_demo_data(s3_bucket, data_dir, unique_app_names: bool):
if s3_bucket is None:
with cd(git_root):
logger.info("Removing old demo data")
shutil.rmtree(data_dir, ignore_errors=True)
if not no_clear_current_data:
shutil.rmtree(data_dir, ignore_errors=True)
generate_all(data_dir=data_dir, unique_app_names=unique_app_names)
else:
generate_all(s3_bucket=s3_bucket, unique_app_names=unique_app_names)
Expand Down
24 changes: 18 additions & 6 deletions burr/tracking/server/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import json
import os.path
import sys
from typing import Any, Optional, Sequence, Type, TypeVar
from typing import Any, Optional, Sequence, Tuple, Type, TypeVar

import aiofiles
import aiofiles.os as aiofilesos
Expand Down Expand Up @@ -101,8 +101,13 @@ async def list_projects(self, request: fastapi.Request) -> Sequence[schema.Proje

@abc.abstractmethod
async def list_apps(
self, request: fastapi.Request, project_id: str, partition_key: Optional[str]
) -> Sequence[schema.ApplicationSummary]:
self,
request: fastapi.Request,
project_id: str,
partition_key: Optional[str],
limit: int,
offset: int,
) -> Tuple[Sequence[schema.ApplicationSummary], int]:
"""Lists out all apps (continual state machine runs with shared state) for a given project.
:param request: The request object, used for authentication/authorization if needed
Expand Down Expand Up @@ -230,8 +235,13 @@ async def _load_metadata(self, metadata_path: str) -> models.ApplicationMetadata
return models.ApplicationMetadataModel()

async def list_apps(
self, request: fastapi.Request, project_id: str, partition_key: Optional[str]
) -> Sequence[ApplicationSummary]:
self,
request: fastapi.Request,
project_id: str,
partition_key: Optional[str],
limit: int = 100,
offset: int = 0,
) -> Tuple[Sequence[ApplicationSummary], bool]:
project_filepath = os.path.join(self.path, project_id)
if not os.path.exists(project_filepath):
return []
Expand Down Expand Up @@ -265,7 +275,9 @@ async def list_apps(
spawning_parent_pointer=metadata.spawning_parent_pointer,
)
)
return out
out = sorted(out, key=lambda x: x.last_written, reverse=True)
# TODO -- actually only get the most recent ones rather than reading everything, this is inefficient
return out[offset : offset + limit], len(out)

async def get_application_logs(
self, request: fastapi.Request, project_id: str, app_id: str, partition_key: Optional[str]
Expand Down
28 changes: 21 additions & 7 deletions burr/tracking/server/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
from starlette.templating import Jinja2Templates

from burr.tracking.server import schema
from burr.tracking.server.schema import ApplicationLogs, BackendSpec, IndexingJob
from burr.tracking.server.schema import (
ApplicationLogs,
ApplicationPage,
BackendSpec,
IndexingJob,
)

# dynamic importing due to the dashes (which make reading the examples on github easier)
email_assistant = importlib.import_module("burr.examples.email-assistant.server")
Expand Down Expand Up @@ -166,12 +171,14 @@ async def get_projects(request: Request) -> Sequence[schema.Project]:
return await backend.list_projects(request)


@app.get(
"/api/v0/{project_id}/{partition_key}/apps", response_model=Sequence[schema.ApplicationSummary]
)
@app.get("/api/v0/{project_id}/{partition_key}/apps", response_model=ApplicationPage)
async def get_apps(
request: Request, project_id: str, partition_key: str
) -> Sequence[schema.ApplicationSummary]:
request: Request,
project_id: str,
partition_key: str,
limit: int = 100,
offset: int = 0,
) -> ApplicationPage:
"""Gets all apps visible by the user
:param request: FastAPI request
Expand All @@ -180,7 +187,14 @@ async def get_apps(
"""
if partition_key == SENTINEL_PARTITION_KEY:
partition_key = None
return await backend.list_apps(request, project_id, partition_key=partition_key)
applications, total_count = await backend.list_apps(
request, project_id, partition_key=partition_key, limit=limit, offset=offset
)
return ApplicationPage(
applications=list(applications),
total=total_count,
has_another_page=total_count > offset + limit,
)


@app.get("/api/v0/{project_id}/{app_id}/{partition_key}/apps")
Expand Down
5 changes: 3 additions & 2 deletions burr/tracking/server/s3/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ async def list_apps(
partition_key: Optional[str],
limit: int = 100,
offset: int = 0,
) -> Sequence[schema.ApplicationSummary]:
) -> Tuple[Sequence[schema.ApplicationSummary], int]:
# TODO -- distinctify between project name and project ID
# Currently they're the same in the UI but we'll want to have them decoupled
app_query = (
Expand Down Expand Up @@ -586,7 +586,8 @@ async def list_apps(
tags={},
)
)
return out
total_app_count = await app_query.count()
return out, total_app_count

async def get_application_logs(
self, request: fastapi.Request, project_id: str, app_id: str, partition_key: str
Expand Down
6 changes: 6 additions & 0 deletions burr/tracking/server/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class ApplicationSummary(pydantic.BaseModel):
spawning_parent_pointer: Optional[PointerModel] = None


class ApplicationPage(pydantic.BaseModel):
applications: List[ApplicationSummary]
total: int
has_another_page: bool


class ApplicationModelWithChildren(pydantic.BaseModel):
application: ApplicationModel
children: List[PointerModel]
Expand Down
1 change: 1 addition & 0 deletions telemetry/ui/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type { OpenAPIConfig } from './core/OpenAPI';
export type { ActionModel } from './models/ActionModel';
export type { ApplicationLogs } from './models/ApplicationLogs';
export type { ApplicationModel } from './models/ApplicationModel';
export type { ApplicationPage } from './models/ApplicationPage';
export type { ApplicationSummary } from './models/ApplicationSummary';
export type { AttributeModel } from './models/AttributeModel';
export type { BackendSpec } from './models/BackendSpec';
Expand Down
16 changes: 12 additions & 4 deletions telemetry/ui/src/api/services/DefaultService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* tslint:disable */
/* eslint-disable */
import type { ApplicationLogs } from '../models/ApplicationLogs';
import type { ApplicationSummary } from '../models/ApplicationSummary';
import type { ApplicationPage } from '../models/ApplicationPage';
import type { BackendSpec } from '../models/BackendSpec';
import type { ChatItem } from '../models/ChatItem';
import type { DraftInit } from '../models/DraftInit';
Expand Down Expand Up @@ -63,20 +63,28 @@ export class DefaultService {
* :return: a list of projects visible by the user
* @param projectId
* @param partitionKey
* @returns ApplicationSummary Successful Response
* @param limit
* @param offset
* @returns ApplicationPage Successful Response
* @throws ApiError
*/
public static getAppsApiV0ProjectIdPartitionKeyAppsGet(
projectId: string,
partitionKey: string
): CancelablePromise<Array<ApplicationSummary>> {
partitionKey: string,
limit: number = 100,
offset?: number
): CancelablePromise<ApplicationPage> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/v0/{project_id}/{partition_key}/apps',
path: {
project_id: projectId,
partition_key: partitionKey
},
query: {
limit: limit,
offset: offset
},
errors: {
422: `Validation Error`
}
Expand Down
9 changes: 5 additions & 4 deletions telemetry/ui/src/components/common/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
* ensure this does what we want.
*/

import { DataInteractive as HeadlessDataInteractive } from '@headlessui/react';
import { Link as RouterLink } from 'react-router-dom';
import React from 'react';

export const Link = React.forwardRef(function Link(
props: { href: string } & React.ComponentPropsWithoutRef<'a'>,
ref: React.ForwardedRef<HTMLAnchorElement>
) {
return (
<HeadlessDataInteractive>
<a {...props} ref={ref} />
</HeadlessDataInteractive>
<RouterLink {...props} to={props.href} ref={ref} />
// <HeadlessDataInteractive>
// <a {...props} ref={ref} />
// </HeadlessDataInteractive>
);
});
Loading

0 comments on commit ff73f02

Please sign in to comment.