Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add definitions for remote store gRPC API as well as the logic for bu… #7674

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

zehiko
Copy link
Contributor

@zehiko zehiko commented Oct 10, 2024

What

In this PR we aim to define initial version of the V0 storage node APIs in the form of grpc protobuf definition. We also want to:

  • settle on code generation
  • type conversions (between rerun internal types and grpc types

(currently) Example usage:

use re_storage_types::v0::{
    storage_node_client::StorageNodeClient, RegisterRecordingsRequest
};

...

  let mut client = StorageNodeClient::connect("http://127.0.0.1:51234")
        .await
        .unwrap();

    let resp = client
        .register_recordings(RegisterRecordingsRequest {
            description: "test".to_string(),
            obj_storage:  ObjectStore {
              url: "dna.rd",
              bucket_name: "my_s3_bucket",
            },
            typ: re_storage_types::v0::RecordingType::Rrd.into(),
        })
        .await
        .unwrap()
        .into_inner();

Checklist

  • I have read and agree to Contributor Guide and the Code of Conduct
  • I've included a screenshot or gif (if applicable)
  • I have tested the web demo (if applicable):
  • The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG
  • If applicable, add a new check to the release checklist!
  • If have noted any breaking changes to the log API in CHANGELOG.md and the migration guide

To run all checks from main, comment on the PR with @rerun-bot full-check.

…ilding rust types from the proto definition

We introduce re_remote_store_types with proto definition files for V0 remote store gRPC API. We also introduce re_remote_store_tpyes_builder
that heaveily relies on tonic_build to build the actual rust code from protobuf files.
Copy link

github-actions bot commented Oct 10, 2024

Deployed docs

Commit Link
96e6dc6 https://landing-b82dabj9z-rerun.vercel.app/docs

@zehiko zehiko self-assigned this Oct 10, 2024
@zehiko zehiko added exclude from changelog PRs with this won't show up in CHANGELOG.md ⛃ re_datastore affects the datastore itself labels Oct 10, 2024
@teh-cmc teh-cmc self-requested a review October 11, 2024 07:53
Copy link
Member

@teh-cmc teh-cmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! A few last things but we're very close.

@@ -16,6 +16,7 @@ pub fn viewer_to_server(
// We set a very high limit, because we should be able to trust the server.
// See https://github.com/rerun-io/rerun/issues/5268 for more
max_incoming_frame_size: 2 * gigs,
delay_blocking: Duration::from_millis(10),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment explaining what this is and why 10ms would be helpful?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait a minute -- that's the wrong README (both the file and the contents)!

Comment on lines +23 to +26
assert!(
workspace_dir.join("CODE_OF_CONDUCT.md").exists(),
"failed to find workspace root"
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't leave future reader extremely confused 😶

Suggested change
assert!(
workspace_dir.join("CODE_OF_CONDUCT.md").exists(),
"failed to find workspace root"
);
// Check for something that only exists in root:
assert!(
workspace_dir.join("CODE_OF_CONDUCT.md").exists(),
"failed to find workspace root"
);

let definitions_dir_path = workspace_dir.join(PROTOBUF_DEFINITIONS_DIR_PATH);
let rust_generated_output_dir_path = workspace_dir.join(RUST_V0_OUTPUT_DIR_PATH);

re_log::info!("Running codegen for storage node types");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
re_log::info!("Running codegen for storage node types");
re_log::info!(
definitions=?definitions_dir_path,
output=?rust_generated_output_dir_path,
"Running codegen for storage node types",
);

message ComponentColumnSelector {
EntityPath entity_path = 1;
Component component = 2;
// TODO do we need join encoding?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for now at the very least -- we'll add it when/if we do.

rpc ListRecordings(ListRecordingsRequest) returns (ListRecordingsResponse) {}
rpc Query(QueryRequest) returns (stream QueryResponse) {}
rpc GetRecordingMetadata(GetRecordingMetadataRequest) returns (GetRecordingMetadataResponse) {}
// TODO (zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and everywhere, this should be TODO(zehiko), not TODO (zehiko).
That's important for all of our TODO-based automated tools to work properly.

The fact that this wasn't caught by the CI is a bug -- I'll make a separate PR for that.

Comment on lines +10 to +15
#![allow(clippy::doc_markdown)]
#![allow(clippy::derive_partial_eq_without_eq)]
#![allow(clippy::enum_variant_names)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::wildcard_imports)]
#![allow(clippy::manual_is_variant_and)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to apply these only to the mod _v0 below.

}
}

impl TryFrom<Query> for re_dataframe::external::re_chunk_store::QueryExpression {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and everywhere you shouldn't need re_dataframe::external::re_chunk_store::QueryExpression, simply re_dataframe::QueryExpression.

If that doesn't work then we have a re-export problem, and it's important to be fixed as these are supposed to be sane-to-use public APIs.

Comment on lines +126 to +133
#[allow(clippy::match_same_arms)]
let timeline = match timeline_name.as_str() {
"log_time" => Self::new_temporal(timeline_name),
"log_tick" => Self::new_sequence(timeline_name),
"frame" => Self::new_sequence(timeline_name),
"frame_nr" => Self::new_sequence(timeline_name),
_ => Self::new_temporal(timeline_name),
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof, that's a huge issue.

This needs a TODO(cmc): QueryExpression::filtered_index gotta be a selector.

Comment on lines +291 to +335
// to chunk store query expression
let expected_qe = re_dataframe::external::re_chunk_store::QueryExpression {
view_contents: Some(BTreeMap::from([(
re_log_types::EntityPath::from("/somepath"),
Some(BTreeSet::from([
re_dataframe::external::re_chunk::ComponentName::new("component"),
])),
)])),
filtered_index: re_log_types::Timeline::new_temporal("log_time"),
filtered_index_range: Some(re_dataframe::external::re_chunk_store::IndexRange::new(
0, 100,
)),
filtered_index_values: Some(
vec![0, 1, 2]
.into_iter()
.map(re_log_types::TimeInt::new_temporal)
.collect::<BTreeSet<_>>(),
),
using_index_values: Some(
vec![3, 4, 5]
.into_iter()
.map(re_log_types::TimeInt::new_temporal)
.collect::<BTreeSet<_>>(),
),
filtered_point_of_view: Some(
re_dataframe::external::re_chunk_store::ComponentColumnSelector {
entity_path: re_log_types::EntityPath::from("/somepath/c"),
component: re_dataframe::external::re_chunk::ComponentName::new("component"),
join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(),
},
),
sparse_fill_strategy:
re_dataframe::external::re_chunk_store::SparseFillStrategy::default(),
selection: Some(vec![
re_dataframe::external::re_chunk_store::ComponentColumnSelector {
entity_path: re_log_types::EntityPath::from("/somepath/c"),
component: re_dataframe::external::re_chunk::ComponentName::new("component"),
join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(),
}
.into(),
]),
};

let query_expression: re_dataframe::external::re_chunk_store::QueryExpression =
query.try_into().unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A full roundtrip would be nice:

let query_grpc_before = /* ... */;
let query_native = query_grpc_before.try_into();
let query_grpc_after =  query_native.into();
assert_eq!(query_grpc_before, query_grpc_after);

at which point you can probably remove the handwritten expectations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
exclude from changelog PRs with this won't show up in CHANGELOG.md ⛃ re_datastore affects the datastore itself
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants