chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:05:14 +08:00
commit 2a547be7fe
7904 changed files with 1000926 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
<!--[metadata]
title = "Server tables"
tags = ["DataFrame", "Tables", "Server", "Cloud",]
thumbnail = "https://static.rerun.io/server_tables/d5155346d84caed5c53de507708c780727c075ef/480w.png"
thumbnail_dimensions = [480, 358]
channel = "main"
include_in_manifest = false
-->
## Writing server tables example
The purpose of this example is to demonstrate how one would set up a data flow where you are incrementally
processing partitions within a dataset. The general concept is that you have two tables that you will use,
one for status and one for results. The purpose of the status table is to have a small table that is easy
to query for partitions that have not yet been processed.
In this example, we first create these two tables. Then we collect the available partitions and compare them
to the status table. To demonstrate how you could batch process a portion of your available data, we simply
take a subset of the returned values that are not yet processed. In customer work flows, you will likely
want to pass all available partitions to work, or you might prefer to send off a single partition at
a time. The details of how you select which partitions to process are up to the individual workflows.
The code in this example produces a few lines of status output and then displays both the results
and status tables.
### Setup
This example will launch the OSS server which will run on `localhost` with a random port.
The example will also create a temporary directory. It will not persist after this script has been executed,
so you will need to restart your server if you want to run the example multiple times. If you prefer
to persist the created table, you can change the remove the `with tempfile.TemporaryDirectory()` line and
instead set a specific location for your files.
### Running
Run the following commands
```bash
pip install -e examples/python/server_tables
python examples/python/server_tables/server_tables.py
```
or to run it via pixi/uv
```bash
pixi run py-build && pixi run uv run examples/python/server_tables/server_tables.py
```
@@ -0,0 +1,12 @@
[project]
name = "server_tables"
version = "0.1.1"
readme = "README.md"
dependencies = ["rerun-sdk", "datafusion==53.0.0"]
[project.scripts]
server_tables = "server_tables:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
+179
View File
@@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""Demonstrates an example workflow of processing datasets and writing to tables."""
from __future__ import annotations
import argparse
import tempfile
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING, cast
import pyarrow as pa
from datafusion import DataFrame, col
from datafusion import functions as F
import rerun as rr
from rerun.server import Server
from rerun.utilities.datafusion.collect import collect_to_string_list
if TYPE_CHECKING:
from rerun.catalog import CatalogClient, DatasetEntry
DATASET_NAME = "dataset"
STATUS_LOG_TABLE_NAME = "status_log"
RESULTS_TABLE_NAME = "results"
def create_table(client: CatalogClient, directory: Path, table_name: str, schema: pa.Schema) -> DataFrame:
"""
Create a lance table at a specified location and return its DataFrame.
This is a convenience function for creating the status log and result tables.
"""
if table_name in client.table_names():
return client.get_table(name=table_name).reader()
url = f"file://{directory}/{table_name}"
return client.create_table(table_name, schema, url).reader()
def create_status_log_table(client: CatalogClient, directory: Path) -> DataFrame:
"""Create the status log table."""
schema = pa.schema([
pa.field("rerun_segment_id", pa.utf8()).with_metadata({rr.SORBET_IS_TABLE_INDEX: "true"}),
pa.field("is_complete", pa.bool_()),
pa.field("update_time", pa.timestamp(unit="ms")),
])
return create_table(client, directory, STATUS_LOG_TABLE_NAME, schema)
def create_results_table(client: CatalogClient, directory: Path) -> DataFrame:
"""Create the results table."""
schema = pa.schema([
("rerun_segment_id", pa.utf8()),
("first_log_time", pa.timestamp(unit="ns")),
("last_log_time", pa.timestamp(unit="ns")),
("first_position_obj1", pa.list_(pa.float32(), 3)),
("first_position_obj2", pa.list_(pa.float32(), 3)),
("first_position_obj3", pa.list_(pa.float32(), 3)),
])
return create_table(client, directory, RESULTS_TABLE_NAME, schema)
def find_missing_segments(segment_table: DataFrame, status_log_table: DataFrame) -> list[str]:
"""Query the status log table for segments that have not processed."""
status_log_table = status_log_table.filter(col("is_complete"))
segments = segment_table.join(status_log_table, on="rerun_segment_id", how="anti")
segment_list = collect_to_string_list(segments, "rerun_segment_id")
# This cast is to satisfy mypy type checking. It is not strictly necessary.
return cast("list[str]", segment_list)
def process_segments(client: CatalogClient, dataset: DatasetEntry, segment_list: list[str]) -> None:
"""
Example code for processing some segments within a dataset.
This example performs a simple aggregation of some of the values stored in the dataset that
might be useful for further processing or metrics extraction. In this work flow we first write
to the status log table that we have started work but set the `is_complete` column to `False`.
When the work is complete we write an additional row setting this column to `True`. Alternate
workflows may only include writing to the table when work is complete. It is sometimes favorable
to keep track of when jobs start and finish so you can produce additional metrics around
when the jobs ran and how long they took.
"""
status_log_table = client.get_table(name=STATUS_LOG_TABLE_NAME)
status_log_table.append(
rerun_segment_id=segment_list,
is_complete=[False] * len(segment_list),
update_time=[datetime.now()] * len(segment_list),
)
df = dataset.filter_segments(segment_list).reader(index="time_1")
df = df.aggregate(
"rerun_segment_id",
[
F.min(col("log_time")).alias("first_log_time"),
F.max(col("log_time")).alias("last_log_time"),
F.first_value(
col("/obj1:Points3D:positions")[0],
filter=col("/obj1:Points3D:positions").is_not_null(),
order_by=col("time_1"),
).alias("first_position_obj1"),
F.first_value(
col("/obj2:Points3D:positions")[0],
filter=col("/obj2:Points3D:positions").is_not_null(),
order_by=col("time_1"),
).alias("first_position_obj2"),
F.first_value(
col("/obj3:Points3D:positions")[0],
filter=col("/obj3:Points3D:positions").is_not_null(),
order_by=col("time_1"),
).alias("first_position_obj3"),
],
)
df.write_table(RESULTS_TABLE_NAME)
# This command will replace the existing rows with a `True` completion status.
# If instead you wish to measure how long it takes your workflow to run, you
# can use an append statement as in the previous write.
status_log_table.upsert(
rerun_segment_id=segment_list,
is_complete=[True] * len(segment_list),
update_time=[datetime.now()] * len(segment_list),
)
def main() -> None:
parser = argparse.ArgumentParser(description="Process some segments in a dataset.")
parser.add_argument("--temp-dir", type=str, default=None, help="Temporary directory to store tables.")
# TODO(#11760): Remove unneeded args when examples infra is fixed.
rr.script_add_args(parser)
args = parser.parse_args()
# TODO(#11760): Fake output to satisfy examples infra.
Path(args.save).touch()
temp_dir = args.temp_dir
if args.temp_dir is not None:
run_example(Path(temp_dir))
else:
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
run_example(temp_path)
def run_example(temp_path: Path) -> None:
root_path = Path(__file__).parent.parent.parent.parent.resolve()
with Server(datasets={DATASET_NAME: root_path / "tests/assets/rrd/dataset"}) as srv:
client = srv.client()
dataset = client.get_dataset(name=DATASET_NAME)
status_log_table = create_status_log_table(client, temp_path)
results_table = create_results_table(client, temp_path)
segment_table = dataset.segment_table().select("rerun_segment_id").distinct()
missing_segments = None
while missing_segments is None or len(missing_segments) != 0:
missing_segments = find_missing_segments(segment_table, status_log_table)
print(f"{len(missing_segments)} of {segment_table.count()} segments have not processed.")
if len(missing_segments) > 0:
process_segments(client, dataset, missing_segments[0:3])
# Show the final results
print("Results table:")
results_table.show()
# Show the final status log table
print("Final status log table:")
status_log_table.show()
if __name__ == "__main__":
main()