Skip to content
Open
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
5 changes: 5 additions & 0 deletions lightly_studio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ start-e2e: build
@echo "Starting server for e2e tests..."
uv run e2e-tests/index_dataset_for_end2end_ui_tests.py

.PHONY: start-coco-10k
start-coco-10k: build
@echo "Starting server for e2e tests with COCO 10k dataset..."
uv run e2e-tests/index_coco_10k.py

.PHONY: start-e2e-with-captions
start-e2e-with-captions: build
@echo "Starting server for e2e tests with captions..."
Expand Down
25 changes: 25 additions & 0 deletions lightly_studio/e2e-tests/index_coco_10k.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""End-to-end demonstration of the lightly_studio dataset loading and UI.

This module provides a simple example of how to load a COCO instance
segmentation dataset and launch the UI application for exploration and
visualization.
"""

from lightly_studio import AnnotationType, Dataset, db_manager, start_gui

# Clean up an existing database
db_manager.connect(cleanup_existing=True)

# Create a Dataset instance
dataset = Dataset.create()

# We point to the annotations json file and the input images folder.
# Defined dataset is processed here to be available for the UI application.
dataset.add_samples_from_coco(
annotations_json="datasets/coco-10k/annotations/instances_train2017.json",
images_path="datasets/coco-10k/images",
annotation_type=AnnotationType.INSTANCE_SEGMENTATION,
)

# We start the UI application on port 8001
start_gui()
13 changes: 11 additions & 2 deletions lightly_studio/src/lightly_studio/api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ def __init__(self, host: str, port: int) -> None:

def start(self) -> None:
"""Start the API server using Uvicorn."""
# start the app
uvicorn.run(app, host=self.host, port=self.port, http="h11")
# start the app with connection limits and timeouts
uvicorn.run(
app,
host=self.host,
port=self.port,
http="h11",
limit_concurrency=1000, # Max concurrent connections
limit_max_requests=10000, # Max requests before worker restart
timeout_keep_alive=5, # Keep-alive timeout in seconds
timeout_graceful_shutdown=30, # Graceful shutdown timeout
)


def _get_available_port(host: str, preferred_port: int, max_tries: int = 50) -> int:
Expand Down
9 changes: 8 additions & 1 deletion lightly_studio/src/lightly_studio/db_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ def __init__(
self._engine_url = engine_url if engine_url else "duckdb:///lightly_studio.db"
if cleanup_existing:
_cleanup_database_file(engine_url=self._engine_url)
self._engine = create_engine(url=self._engine_url, poolclass=poolclass)
# Total available connections = pool_size + max_overflow = 20 + 40 = 60
# (default is (pool_size=5, max_overflow=10))
self._engine = create_engine(
url=self._engine_url,
poolclass=poolclass,
pool_size=20,
max_overflow=40,
)
SQLModel.metadata.create_all(self._engine)

@contextmanager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@
{:else if $infiniteSamples.isSuccess && samples.length === 0}
<!-- Empty state -->
<div class="flex h-full w-full items-center justify-center">
<div class="text-center text-muted-foreground">
<div class="text-muted-foreground text-center">
<div class="mb-2 text-lg font-medium">No samples found</div>
<div class="text-sm">This dataset doesn't contain any samples.</div>
</div>
Expand Down Expand Up @@ -292,6 +292,7 @@
class="relative overflow-hidden rounded-lg"
style="width: var(--sample-width); height: var(--sample-height);"
>
Index:{index}
<SampleImage sample={samples[index]} {objectFit} />
<SampleAnnotations
sample={samples[index]}
Expand Down
Loading