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

feat: (new) count docs and assets #702

Merged
merged 3 commits into from
Aug 24, 2024
Merged
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
2 changes: 2 additions & 0 deletions src/declarations/satellite/satellite.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,10 @@ export interface UploadChunkResult {
export interface _SERVICE {
build_version: ActorMethod<[], string>;
commit_asset_upload: ActorMethod<[CommitBatch], undefined>;
count_assets: ActorMethod<[string, ListParams], bigint>;
count_collection_assets: ActorMethod<[string], bigint>;
count_collection_docs: ActorMethod<[string], bigint>;
count_docs: ActorMethod<[string, ListParams], bigint>;
del_asset: ActorMethod<[string, string], undefined>;
del_assets: ActorMethod<[string], undefined>;
del_controllers: ActorMethod<[DeleteControllersArgs], Array<[Principal, Controller]>>;
Expand Down
58 changes: 30 additions & 28 deletions src/declarations/satellite/satellite.factory.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,34 @@ export const idlFactory = ({ IDL }) => {
headers: IDL.Vec(IDL.Tuple(IDL.Text, IDL.Text)),
chunk_ids: IDL.Vec(IDL.Nat)
});
const ListOrderField = IDL.Variant({
UpdatedAt: IDL.Null,
Keys: IDL.Null,
CreatedAt: IDL.Null
});
const ListOrder = IDL.Record({ field: ListOrderField, desc: IDL.Bool });
const TimestampMatcher = IDL.Variant({
Equal: IDL.Nat64,
Between: IDL.Tuple(IDL.Nat64, IDL.Nat64),
GreaterThan: IDL.Nat64,
LessThan: IDL.Nat64
});
const ListMatcher = IDL.Record({
key: IDL.Opt(IDL.Text),
updated_at: IDL.Opt(TimestampMatcher),
description: IDL.Opt(IDL.Text),
created_at: IDL.Opt(TimestampMatcher)
});
const ListPaginate = IDL.Record({
start_after: IDL.Opt(IDL.Text),
limit: IDL.Opt(IDL.Nat64)
});
const ListParams = IDL.Record({
order: IDL.Opt(ListOrder),
owner: IDL.Opt(IDL.Principal),
matcher: IDL.Opt(ListMatcher),
paginate: IDL.Opt(ListPaginate)
});
const DeleteControllersArgs = IDL.Record({
controllers: IDL.Vec(IDL.Principal)
});
Expand Down Expand Up @@ -136,34 +164,6 @@ export const idlFactory = ({ IDL }) => {
full_path: IDL.Text
});
const InitUploadResult = IDL.Record({ batch_id: IDL.Nat });
const ListOrderField = IDL.Variant({
UpdatedAt: IDL.Null,
Keys: IDL.Null,
CreatedAt: IDL.Null
});
const ListOrder = IDL.Record({ field: ListOrderField, desc: IDL.Bool });
const TimestampMatcher = IDL.Variant({
Equal: IDL.Nat64,
Between: IDL.Tuple(IDL.Nat64, IDL.Nat64),
GreaterThan: IDL.Nat64,
LessThan: IDL.Nat64
});
const ListMatcher = IDL.Record({
key: IDL.Opt(IDL.Text),
updated_at: IDL.Opt(TimestampMatcher),
description: IDL.Opt(IDL.Text),
created_at: IDL.Opt(TimestampMatcher)
});
const ListPaginate = IDL.Record({
start_after: IDL.Opt(IDL.Text),
limit: IDL.Opt(IDL.Nat64)
});
const ListParams = IDL.Record({
order: IDL.Opt(ListOrder),
owner: IDL.Opt(IDL.Principal),
matcher: IDL.Opt(ListMatcher),
paginate: IDL.Opt(ListPaginate)
});
const ListResults = IDL.Record({
matches_pages: IDL.Opt(IDL.Nat64),
matches_length: IDL.Nat64,
Expand Down Expand Up @@ -234,8 +234,10 @@ export const idlFactory = ({ IDL }) => {
return IDL.Service({
build_version: IDL.Func([], [IDL.Text], ['query']),
commit_asset_upload: IDL.Func([CommitBatch], [], []),
count_assets: IDL.Func([IDL.Text, ListParams], [IDL.Nat64], ['query']),
count_collection_assets: IDL.Func([IDL.Text], [IDL.Nat64], ['query']),
count_collection_docs: IDL.Func([IDL.Text], [IDL.Nat64], ['query']),
count_docs: IDL.Func([IDL.Text, ListParams], [IDL.Nat64], ['query']),
del_asset: IDL.Func([IDL.Text, IDL.Text], [], []),
del_assets: IDL.Func([IDL.Text], [], []),
del_controllers: IDL.Func(
Expand Down
58 changes: 30 additions & 28 deletions src/declarations/satellite/satellite.factory.did.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,34 @@ export const idlFactory = ({ IDL }) => {
headers: IDL.Vec(IDL.Tuple(IDL.Text, IDL.Text)),
chunk_ids: IDL.Vec(IDL.Nat)
});
const ListOrderField = IDL.Variant({
UpdatedAt: IDL.Null,
Keys: IDL.Null,
CreatedAt: IDL.Null
});
const ListOrder = IDL.Record({ field: ListOrderField, desc: IDL.Bool });
const TimestampMatcher = IDL.Variant({
Equal: IDL.Nat64,
Between: IDL.Tuple(IDL.Nat64, IDL.Nat64),
GreaterThan: IDL.Nat64,
LessThan: IDL.Nat64
});
const ListMatcher = IDL.Record({
key: IDL.Opt(IDL.Text),
updated_at: IDL.Opt(TimestampMatcher),
description: IDL.Opt(IDL.Text),
created_at: IDL.Opt(TimestampMatcher)
});
const ListPaginate = IDL.Record({
start_after: IDL.Opt(IDL.Text),
limit: IDL.Opt(IDL.Nat64)
});
const ListParams = IDL.Record({
order: IDL.Opt(ListOrder),
owner: IDL.Opt(IDL.Principal),
matcher: IDL.Opt(ListMatcher),
paginate: IDL.Opt(ListPaginate)
});
const DeleteControllersArgs = IDL.Record({
controllers: IDL.Vec(IDL.Principal)
});
Expand Down Expand Up @@ -136,34 +164,6 @@ export const idlFactory = ({ IDL }) => {
full_path: IDL.Text
});
const InitUploadResult = IDL.Record({ batch_id: IDL.Nat });
const ListOrderField = IDL.Variant({
UpdatedAt: IDL.Null,
Keys: IDL.Null,
CreatedAt: IDL.Null
});
const ListOrder = IDL.Record({ field: ListOrderField, desc: IDL.Bool });
const TimestampMatcher = IDL.Variant({
Equal: IDL.Nat64,
Between: IDL.Tuple(IDL.Nat64, IDL.Nat64),
GreaterThan: IDL.Nat64,
LessThan: IDL.Nat64
});
const ListMatcher = IDL.Record({
key: IDL.Opt(IDL.Text),
updated_at: IDL.Opt(TimestampMatcher),
description: IDL.Opt(IDL.Text),
created_at: IDL.Opt(TimestampMatcher)
});
const ListPaginate = IDL.Record({
start_after: IDL.Opt(IDL.Text),
limit: IDL.Opt(IDL.Nat64)
});
const ListParams = IDL.Record({
order: IDL.Opt(ListOrder),
owner: IDL.Opt(IDL.Principal),
matcher: IDL.Opt(ListMatcher),
paginate: IDL.Opt(ListPaginate)
});
const ListResults = IDL.Record({
matches_pages: IDL.Opt(IDL.Nat64),
matches_length: IDL.Nat64,
Expand Down Expand Up @@ -234,8 +234,10 @@ export const idlFactory = ({ IDL }) => {
return IDL.Service({
build_version: IDL.Func([], [IDL.Text], ['query']),
commit_asset_upload: IDL.Func([CommitBatch], [], []),
count_assets: IDL.Func([IDL.Text, ListParams], [IDL.Nat64], ['query']),
count_collection_assets: IDL.Func([IDL.Text], [IDL.Nat64], ['query']),
count_collection_docs: IDL.Func([IDL.Text], [IDL.Nat64], ['query']),
count_docs: IDL.Func([IDL.Text, ListParams], [IDL.Nat64], ['query']),
del_asset: IDL.Func([IDL.Text, IDL.Text], [], []),
del_assets: IDL.Func([IDL.Text], [], []),
del_controllers: IDL.Func(
Expand Down
2 changes: 2 additions & 0 deletions src/libs/satellite/satellite.did
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,10 @@ type UploadChunk = record {
type UploadChunkResult = record { chunk_id : nat };
service : () -> {
commit_asset_upload : (CommitBatch) -> ();
count_assets : (text, ListParams) -> (nat64) query;
count_collection_assets : (text) -> (nat64) query;
count_collection_docs : (text) -> (nat64) query;
count_docs : (text, ListParams) -> (nat64) query;
del_asset : (text, text) -> ();
del_assets : (text) -> ();
del_controllers : (DeleteControllersArgs) -> (
Expand Down
28 changes: 28 additions & 0 deletions src/libs/satellite/src/db/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,34 @@ pub fn list_docs_store(
secure_get_docs(caller, &controllers, collection, filter)
}

/// Count documents in a collection.
///
/// This function retrieves the count of documents from a collection's store based on the specified parameters.
/// It returns a `Result<usize, String>` where `Ok(usize)` contains the count of documents matching the filter criteria,
/// or an error message as `Err(String)` if the operation encounters issues.
///
/// # Parameters
/// - `caller`: The `Principal` representing the caller initiating the operation. If used in serverless functions, you can use `ic_cdk::id()` to pass an administrator controller.
/// - `collection`: A `CollectionKey` representing the collection from which to count the documents.
/// - `filter`: A reference to `ListParams` containing the filter criteria for counting the documents.
///
/// # Returns
/// - `Ok(usize)`: Contains the count of documents matching the filter criteria.
/// - `Err(String)`: An error message if the operation fails.
///
/// This function counts documents in a Juno collection's store by listing them and then determining the length of the result set.
///
/// # Note
/// This implementation can be improved, as it currently relies on `list_docs_store` underneath, meaning that all documents matching the filter criteria are still read from the store. This might lead to unnecessary overhead, especially for large collections. Optimizing this function to count documents directly without retrieving them could enhance performance.
pub fn count_docs_store(
caller: Principal,
collection: CollectionKey,
filter: &ListParams,
) -> Result<usize, String> {
let results = list_docs_store(caller, collection, filter)?;
Ok(results.items_length)
}

fn secure_get_docs(
caller: Principal,
controllers: &Controllers,
Expand Down
36 changes: 24 additions & 12 deletions src/libs/satellite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use junobuild_storage::types::interface::{
// Re-export types

pub use crate::db::store::{
count_collection_docs_store, delete_doc_store, delete_docs_store, get_doc_store, list_docs_store,
set_doc_store,
count_collection_docs_store, count_docs_store, delete_doc_store, delete_docs_store,
get_doc_store, list_docs_store, set_doc_store,
};
use crate::db::types::config::DbConfig;
pub use crate::db::types::interface::{DelDoc, SetDoc};
Expand All @@ -50,8 +50,8 @@ pub use crate::logs::loggers::{
pub use crate::logs::types::logs::{Log, LogLevel};
pub use crate::storage::handlers::set_asset_handler;
pub use crate::storage::store::{
count_collection_assets_store, delete_asset_store, delete_assets_store, get_asset_store,
get_content_chunks_store, list_assets_store,
count_assets_store, count_collection_assets_store, delete_asset_store, delete_assets_store,
get_asset_store, get_content_chunks_store, list_assets_store,
};
pub use crate::types::hooks::{
AssertDeleteAssetContext, AssertDeleteDocContext, AssertSetDocContext,
Expand Down Expand Up @@ -118,6 +118,12 @@ pub fn list_docs(collection: CollectionKey, filter: ListParams) -> ListResults<D
satellite::list_docs(collection, filter)
}

#[doc(hidden)]
#[query]
pub fn count_docs(collection: CollectionKey, filter: ListParams) -> usize {
satellite::count_docs(collection, filter)
}

#[doc(hidden)]
#[query]
pub fn get_many_docs(docs: Vec<(CollectionKey, Key)>) -> Vec<(Key, Option<Doc>)> {
Expand Down Expand Up @@ -316,6 +322,12 @@ pub fn list_assets(collection: CollectionKey, filter: ListParams) -> ListResults
satellite::list_assets(collection, filter)
}

#[doc(hidden)]
#[query]
pub fn count_assets(collection: CollectionKey, filter: ListParams) -> usize {
satellite::count_assets(collection, filter)
}

#[doc(hidden)]
#[update]
pub fn del_asset(collection: CollectionKey, full_path: FullPath) {
Expand Down Expand Up @@ -395,14 +407,14 @@ pub fn memory_size() -> MemorySize {
macro_rules! include_satellite {
() => {
use junobuild_satellite::{
commit_asset_upload, count_collection_assets, count_collection_docs, del_asset, del_assets, del_controllers,
del_custom_domain, del_doc, del_docs, del_many_assets, del_many_docs, del_rule,
deposit_cycles, get_asset, get_auth_config, get_config, get_db_config, get_doc,
get_many_assets, get_many_docs, get_storage_config, http_request,
http_request_streaming_callback, init, init_asset_upload, list_assets,
list_controllers, list_custom_domains, list_docs, list_rules, memory_size,
post_upgrade, pre_upgrade, set_auth_config, set_controllers, set_custom_domain,
set_db_config, set_doc, set_many_docs, set_rule, set_storage_config,
commit_asset_upload, count_assets, count_collection_assets, count_collection_docs,
count_docs, del_asset, del_assets, del_controllers, del_custom_domain, del_doc,
del_docs, del_many_assets, del_many_docs, del_rule, deposit_cycles, get_asset,
get_auth_config, get_config, get_db_config, get_doc, get_many_assets, get_many_docs,
get_storage_config, http_request, http_request_streaming_callback, init,
init_asset_upload, list_assets, list_controllers, list_custom_domains, list_docs,
list_rules, memory_size, post_upgrade, pre_upgrade, set_auth_config, set_controllers,
set_custom_domain, set_db_config, set_doc, set_many_docs, set_rule, set_storage_config,
upload_asset_chunk, version,
};

Expand Down
35 changes: 29 additions & 6 deletions src/libs/satellite/src/satellite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use crate::controllers::store::{
set_controllers as set_controllers_store,
};
use crate::db::store::{
count_collection_docs_store, delete_doc_store, delete_docs_store, get_config_store as get_db_config_store,
get_doc_store, list_docs_store, set_config_store as set_db_config_store, set_doc_store,
count_collection_docs_store, count_docs_store, delete_doc_store, delete_docs_store,
get_config_store as get_db_config_store, get_doc_store, list_docs_store,
set_config_store as set_db_config_store, set_doc_store,
};
use crate::db::types::config::DbConfig;
use crate::db::types::interface::{DelDoc, SetDoc};
Expand All @@ -25,10 +26,10 @@ use crate::rules::store::{
};
use crate::storage::certified_assets::upgrade::defer_init_certified_assets;
use crate::storage::store::{
commit_batch_store, count_collection_assets_store, create_batch_store, create_chunk_store,
delete_asset_store, delete_assets_store, delete_domain_store, get_asset_store,
get_config_store as get_storage_config_store, get_custom_domains_store, list_assets_store,
set_config_store as set_storage_config_store, set_domain_store,
commit_batch_store, count_assets_store, count_collection_assets_store, create_batch_store,
create_chunk_store, delete_asset_store, delete_assets_store, delete_domain_store,
get_asset_store, get_config_store as get_storage_config_store, get_custom_domains_store,
list_assets_store, set_config_store as set_storage_config_store, set_domain_store,
};
use crate::storage::strategy_impls::StorageState;
use crate::types::interface::{Config, RulesType};
Expand Down Expand Up @@ -153,6 +154,17 @@ pub fn list_docs(collection: CollectionKey, filter: ListParams) -> ListResults<D
}
}

pub fn count_docs(collection: CollectionKey, filter: ListParams) -> usize {
let caller = caller();

let result = count_docs_store(caller, collection, &filter);

match result {
Ok(value) => value,
Err(error) => trap(&error),
}
}

pub fn get_many_docs(docs: Vec<(CollectionKey, Key)>) -> Vec<(Key, Option<Doc>)> {
docs.iter()
.map(|(collection, key)| {
Expand Down Expand Up @@ -405,6 +417,17 @@ pub fn list_assets(collection: CollectionKey, filter: ListParams) -> ListResults
}
}

pub fn count_assets(collection: CollectionKey, filter: ListParams) -> usize {
let caller = caller();

let result = count_assets_store(caller, &collection, &filter);

match result {
Ok(result) => result,
Err(error) => trap(&["Assets cannot be counted: ".to_string(), error].join("")),
}
}

pub fn del_asset(collection: CollectionKey, full_path: FullPath) {
let caller = caller();

Expand Down
Loading