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
23 changes: 23 additions & 0 deletions lore-proto/proto/lore/repository/v1/repository.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ service RepositoryService {
rpc RepositoryGet (RepositoryGetRequest) returns (RepositoryGetResponse);
// Stream all repositories the caller is authorised to see.
rpc RepositoryList (RepositoryListRequest) returns (stream RepositoryListResponse);
// Count the repositories the caller is authorised to see, without
// enumerating them. Applies the same optional filters as
// `RepositoryList`. Cheaper than `RepositoryList` because no per-repo
// metadata is streamed back to the caller; when no filter is set, the
// server can answer from the repository id set alone.
rpc RepositoryCount (RepositoryCountRequest) returns (RepositoryCountResponse);
// Cheap hash-only read of a repository's current metadata pointer.
rpc RepositoryMetadataGet(RepositoryMetadataGetRequest) returns (RepositoryMetadataGetResponse);
// Compare-and-swap update of a repository's metadata pointer. CAS miss is
Expand Down Expand Up @@ -118,6 +124,23 @@ message RepositoryListResponse {
lore.model.v1.Repository repository = 1;
}

// Request to count repositories the caller is authorised to see. Filter
// semantics mirror `RepositoryListRequest`; a repository is counted iff
// `RepositoryList` with the same filters would emit it.
message RepositoryCountRequest {
// If set, only repositories whose `creator` field is an exact
// byte-for-byte case-sensitive match are counted.
optional string creator = 1;
}

// Response carrying the count of matching repositories. `count` defaults
// to zero, so an absent or unset value is safe to read as zero.
message RepositoryCountResponse {
// Number of repositories matching the request's filters and the
// caller's authorisation.
uint64 count = 1;
}

// Request for a cheap hash-only read of a repository's metadata pointer.
message RepositoryMetadataGetRequest {
// Repository id.
Expand Down
131 changes: 131 additions & 0 deletions lore-proto/src/grpc/lore.repository.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,45 @@ impl ::prost::Name for RepositoryListResponse {
"/lore.repository.v1.RepositoryListResponse".into()
}
}
/// Request to count repositories the caller is authorised to see. Filter
/// semantics mirror `RepositoryListRequest`; a repository is counted iff
/// `RepositoryList` with the same filters would emit it.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RepositoryCountRequest {
/// If set, only repositories whose `creator` field is an exact
/// byte-for-byte case-sensitive match are counted.
#[prost(string, optional, tag = "1")]
pub creator: ::core::option::Option<::prost::alloc::string::String>,
}
impl ::prost::Name for RepositoryCountRequest {
const NAME: &'static str = "RepositoryCountRequest";
const PACKAGE: &'static str = "lore.repository.v1";
fn full_name() -> ::prost::alloc::string::String {
"lore.repository.v1.RepositoryCountRequest".into()
}
fn type_url() -> ::prost::alloc::string::String {
"/lore.repository.v1.RepositoryCountRequest".into()
}
}
/// Response carrying the count of matching repositories. `count` defaults
/// to zero, so an absent or unset value is safe to read as zero.
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RepositoryCountResponse {
/// Number of repositories matching the request's filters and the
/// caller's authorisation.
#[prost(uint64, tag = "1")]
pub count: u64,
}
impl ::prost::Name for RepositoryCountResponse {
const NAME: &'static str = "RepositoryCountResponse";
const PACKAGE: &'static str = "lore.repository.v1";
fn full_name() -> ::prost::alloc::string::String {
"lore.repository.v1.RepositoryCountResponse".into()
}
fn type_url() -> ::prost::alloc::string::String {
"/lore.repository.v1.RepositoryCountResponse".into()
}
}
/// Request for a cheap hash-only read of a repository's metadata pointer.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RepositoryMetadataGetRequest {
Expand Down Expand Up @@ -484,6 +523,40 @@ pub mod repository_service_client {
);
self.inner.server_streaming(req, path, codec).await
}
/// Count the repositories the caller is authorised to see, without
/// enumerating them. Applies the same optional filters as
/// `RepositoryList`. Cheaper than `RepositoryList` because no per-repo
/// metadata is streamed back to the caller; when no filter is set, the
/// server can answer from the repository id set alone.
pub async fn repository_count(
&mut self,
request: impl tonic::IntoRequest<super::RepositoryCountRequest>,
) -> std::result::Result<
tonic::Response<super::RepositoryCountResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/lore.repository.v1.RepositoryService/RepositoryCount",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(
GrpcMethod::new(
"lore.repository.v1.RepositoryService",
"RepositoryCount",
),
);
self.inner.unary(req, path, codec).await
}
/// Cheap hash-only read of a repository's current metadata pointer.
pub async fn repository_metadata_get(
&mut self,
Expand Down Expand Up @@ -603,6 +676,18 @@ pub mod repository_service_server {
tonic::Response<Self::RepositoryListStream>,
tonic::Status,
>;
/// Count the repositories the caller is authorised to see, without
/// enumerating them. Applies the same optional filters as
/// `RepositoryList`. Cheaper than `RepositoryList` because no per-repo
/// metadata is streamed back to the caller; when no filter is set, the
/// server can answer from the repository id set alone.
async fn repository_count(
&self,
request: tonic::Request<super::RepositoryCountRequest>,
) -> std::result::Result<
tonic::Response<super::RepositoryCountResponse>,
tonic::Status,
>;
/// Cheap hash-only read of a repository's current metadata pointer.
async fn repository_metadata_get(
&self,
Expand Down Expand Up @@ -887,6 +972,52 @@ pub mod repository_service_server {
};
Box::pin(fut)
}
"/lore.repository.v1.RepositoryService/RepositoryCount" => {
#[allow(non_camel_case_types)]
struct RepositoryCountSvc<T: RepositoryService>(pub Arc<T>);
impl<
T: RepositoryService,
> tonic::server::UnaryService<super::RepositoryCountRequest>
for RepositoryCountSvc<T> {
type Response = super::RepositoryCountResponse;
type Future = BoxFuture<
tonic::Response<Self::Response>,
tonic::Status,
>;
fn call(
&mut self,
request: tonic::Request<super::RepositoryCountRequest>,
) -> Self::Future {
let inner = Arc::clone(&self.0);
let fut = async move {
<T as RepositoryService>::repository_count(&inner, request)
.await
};
Box::pin(fut)
}
}
let accept_compression_encodings = self.accept_compression_encodings;
let send_compression_encodings = self.send_compression_encodings;
let max_decoding_message_size = self.max_decoding_message_size;
let max_encoding_message_size = self.max_encoding_message_size;
let inner = self.inner.clone();
let fut = async move {
let method = RepositoryCountSvc(inner);
let codec = tonic_prost::ProstCodec::default();
let mut grpc = tonic::server::Grpc::new(codec)
.apply_compression_config(
accept_compression_encodings,
send_compression_encodings,
)
.apply_max_message_size_config(
max_decoding_message_size,
max_encoding_message_size,
);
let res = grpc.unary(method, req).await;
Ok(res)
};
Box::pin(fut)
}
"/lore.repository.v1.RepositoryService/RepositoryMetadataGet" => {
#[allow(non_camel_case_types)]
struct RepositoryMetadataGetSvc<T: RepositoryService>(pub Arc<T>);
Expand Down
9 changes: 8 additions & 1 deletion lore-proto/tests/v1_repository.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// SPDX-FileCopyrightText: 2026 Epic Games, Inc.
// SPDX-License-Identifier: MIT
//! Smoke test verifying `lore.repository.v1` carries the 6 RPCs' request /
//! Smoke test verifying `lore.repository.v1` carries the 7 RPCs' request /
//! response messages.

use lore_proto::lore::repository::v1::RepositoryCountRequest;
use lore_proto::lore::repository::v1::RepositoryCountResponse;
use lore_proto::lore::repository::v1::RepositoryCreateRequest;
use lore_proto::lore::repository::v1::RepositoryCreateResponse;
use lore_proto::lore::repository::v1::RepositoryDeleteRequest;
Expand All @@ -27,6 +29,8 @@ fn v1_repository_request_response_types_default() {
let _ = RepositoryGetResponse::default();
let _ = RepositoryListRequest::default();
let _ = RepositoryListResponse::default();
let _ = RepositoryCountRequest::default();
let _ = RepositoryCountResponse::default();
let _ = RepositoryMetadataGetRequest::default();
let _ = RepositoryMetadataGetResponse::default();
let _ = RepositoryMetadataSetRequest::default();
Expand Down Expand Up @@ -60,6 +64,9 @@ fn v1_repository_field_shapes() {
let RepositoryListRequest { creator: _ } = RepositoryListRequest::default();
let RepositoryListResponse { repository: _ } = RepositoryListResponse::default();

let RepositoryCountRequest { creator: _ } = RepositoryCountRequest::default();
let RepositoryCountResponse { count: _ } = RepositoryCountResponse::default();

let RepositoryMetadataGetRequest { id: _ } = RepositoryMetadataGetRequest::default();
let RepositoryMetadataGetResponse { metadata: _ } = RepositoryMetadataGetResponse::default();

Expand Down
1 change: 1 addition & 0 deletions lore-server/src/grpc/repository/v1/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-FileCopyrightText: 2026 Epic Games, Inc.
// SPDX-License-Identifier: MIT
pub mod repository_count;
pub mod repository_create;
pub mod repository_delete;
pub mod repository_get;
Expand Down
Loading