Skip to content
This repository has been archived by the owner on Feb 3, 2023. It is now read-only.

implemented different types of pagination #2110

Merged
merged 10 commits into from
Feb 12, 2020
2 changes: 1 addition & 1 deletion CHANGELOG-UNRELEASED.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Added

### Changed

- Changed Pagination to have different types [#2110](https://github.com/holochain/holochain-rust/pull/2110)
### Deprecated

### Removed
Expand Down
35 changes: 35 additions & 0 deletions app_spec/test/files/links.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { one, two } = require('../config')
const sleep = require('sleep')

module.exports = scenario => {
scenario('delete_post', async (s, t) => {
Copy link
Member

Choose a reason for hiding this comment

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

Why is this scenario called "delete_post"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Woops that is not a new scenario but I have just added sleep in there :)

Expand Down Expand Up @@ -132,6 +133,40 @@ module.exports = scenario => {

t.equal(1, bob_posts_live_2.Ok.links.length)
t.equal(1, alice_posts_live_2.Ok.links.length)
sleep.sleep(5);
const bob_posts_live_time = await bob.call('app', 'simple', 'get_my_links_with_time_pagination',
{
base: alice.info('app').agentAddress,
from_seconds: Math.floor(new Date() / 1000),//last ever second
limit:3
})

const alice_posts_live_time = await bob.call('app', 'simple', 'get_my_links_with_time_pagination',
{
base: alice.info('app').agentAddress,
from_seconds: Math.floor(new Date() / 1000),//last ever second
limit:3
})

t.equal(0, bob_posts_live_time.Ok.links.length)
t.equal(0, alice_posts_live_time.Ok.links.length)

const bob_posts_time_2 = await bob.call('app', 'simple', 'get_my_links_with_time_pagination',
{
base: alice.info('app').agentAddress,
from_seconds: 0,//first ever second
limit:3
})

const alice_posts_time_2 = await bob.call('app', 'simple', 'get_my_links_with_time_pagination',
{
base: alice.info('app').agentAddress,
from_seconds: 0,//first ever second
limit:3
})

t.equal(3, bob_posts_time_2.Ok.links.length)
t.equal(3, alice_posts_time_2.Ok.links.length)
})

scenario('get_links_crud', async (s, t) => {
Expand Down
18 changes: 16 additions & 2 deletions app_spec/zomes/simple/code/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,16 @@ pub fn handle_get_my_links_with_tag(agent : Address,status_request:LinksStatusRe
pub fn handle_get_my_links_with_pagination(agent : Address,pagesize:usize,pagenumber:usize) ->ZomeApiResult<GetLinksResult>
{
let options = GetLinksOptions{
pagination : Some(Pagination{page_size : pagesize,page_number : pagenumber}),
pagination : Some(Pagination::Size(SizePagination{page_size : pagesize,page_number : pagenumber})),
..GetLinksOptions::default()
};
hdk::get_links_with_options(&agent, LinkMatch::Exactly("authored_simple_posts"), LinkMatch::Any,options)
}

pub fn handle_get_my_links_with_time_pagination(agent : Address,from_seconds:i64,limit:usize) ->ZomeApiResult<GetLinksResult>
StaticallyTypedAnxiety marked this conversation as resolved.
Show resolved Hide resolved
{
let options = GetLinksOptions{
pagination : Some(Pagination::Time(TimePagination{from_time : Iso8601::new(from_seconds,0),limit})),
..GetLinksOptions::default()
};
hdk::get_links_with_options(&agent, LinkMatch::Exactly("authored_simple_posts"), LinkMatch::Any,options)
Expand Down Expand Up @@ -208,6 +217,11 @@ define_zome! {
outputs: |result: ZomeApiResult<GetLinksResult>|,
handler: handle_get_my_links_with_pagination
}
get_my_links_with_time_pagination: {
inputs: |base: Address,from_seconds:i64,limit:usize|,
outputs: |result: ZomeApiResult<GetLinksResult>|,
handler: handle_get_my_links_with_time_pagination
}
get_my_links_count: {
inputs: |base: Address,status_request:LinksStatusRequestKind,tag:String|,
outputs: |result: ZomeApiResult<GetLinksResultCount>|,
Expand All @@ -231,6 +245,6 @@ define_zome! {
]

traits: {
hc_public [create_anchor, get_entry, create_link, delete_link, get_my_links, test_emit_signal,get_my_links_count,create_link_with_tag,get_my_links_count_by_tag,delete_link_with_tag,get_my_links_with_tag,encrypt,decrypt,get_my_links_with_pagination]
hc_public [create_anchor, get_entry, create_link, delete_link, get_my_links, test_emit_signal,get_my_links_count,create_link_with_tag,get_my_links_count_by_tag,delete_link_with_tag,get_my_links_with_tag,encrypt,decrypt,get_my_links_with_pagination,get_my_links_with_time_pagination]
}
}
2 changes: 1 addition & 1 deletion crates/core/src/agent/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ pub fn create_entry_with_header_for_header(
root_state: &StateWrapper,
chain_header: ChainHeader,
) -> Result<EntryWithHeader, HolochainError> {
let timestamp = chain_header.timestamp().clone();
let timestamp = *chain_header.timestamp();
let entry = Entry::ChainHeader(chain_header);
// This header entry needs its own header so we can publish it.
// This is a bit delicate:
Expand Down
40 changes: 27 additions & 13 deletions crates/core/src/dht/dht_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use holochain_core_types::{
error::{HcResult, HolochainError},
network::{
entry_aspect::EntryAspect,
query::{GetLinksQueryConfiguration, SortOrder},
query::{GetLinksQueryConfiguration, Pagination, SortOrder},
},
};
use holochain_json_api::{error::JsonError, json::JsonString};
Expand All @@ -29,6 +29,7 @@ use holochain_persistence_api::{
use regex::Regex;

use crate::{dht::pending_validations::PendingValidation, state::StateWrapper};
use chrono::{offset::FixedOffset, DateTime};
use holochain_json_api::error::JsonResult;
use holochain_persistence_api::error::PersistenceResult;
use std::{
Expand Down Expand Up @@ -176,18 +177,31 @@ impl DhtStore {
SortOrder::Ascending => Box::new(filtered.into_iter()),
SortOrder::Descending => Box::new(filtered.into_iter().rev()),
};
Ok(filter_with_sort_order
.skip(
pagination
.clone()
.map(|page| page.page_size * page.page_number)
.unwrap_or(0),
)
.take(
pagination
.map(|page| page.page_size)
.unwrap_or(std::usize::MAX),
)
let filter_with_pagination: Box<dyn Iterator<Item = EntityAttributeValueIndex>> =
match pagination {
Some(paginate) => match paginate {
Pagination::Time(time_pagination) => {
let paginated_time = time_pagination.clone();
Box::new(
filter_with_sort_order
.skip_while(move |eavi| {
let from_time: DateTime<FixedOffset> =
paginated_time.from_time.into();
from_time.timestamp_nanos() >= eavi.index()
})
.take(time_pagination.limit),
)
}
Pagination::Size(size_pagination) => Box::new(
filter_with_sort_order
.skip(size_pagination.page_size * size_pagination.page_number)
.take(size_pagination.page_size),
),
},
None => filter_with_sort_order,
};

Ok(filter_with_pagination
.map(|s| match s.attribute() {
Attribute::LinkTag(_, _) => (s, CrudStatus::Live),
_ => (s, CrudStatus::Deleted),
Expand Down
17 changes: 15 additions & 2 deletions crates/core_types/src/network/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{chain_header::ChainHeader, crud_status::CrudStatus, entry::EntryWithMetaAndHeader};
use crate::{
chain_header::ChainHeader, crud_status::CrudStatus, entry::EntryWithMetaAndHeader,
time::Iso8601,
};
use holochain_json_api::{error::JsonError, json::JsonString};
use holochain_persistence_api::{cas::content::Address, eav::Value};

Expand All @@ -16,11 +19,21 @@ impl Default for SortOrder {
}
}

#[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq, Hash, DefaultJson)]
pub struct TimePagination {
pub from_time: Iso8601,
pub limit: usize,
}
#[derive(Deserialize, Default, Debug, Serialize, Clone, PartialEq, Eq, Hash, DefaultJson)]
pub struct Pagination {
pub struct SizePagination {
pub page_number: usize,
pub page_size: usize,
}
#[derive(Deserialize, Debug, Serialize, Clone, PartialEq, Eq, Hash, DefaultJson)]
pub enum Pagination {
Size(SizePagination),
Time(TimePagination),
}

#[derive(Debug, Serialize, Deserialize, PartialEq, DefaultJson, Clone, Default)]
pub struct GetLinksQueryConfiguration {
Expand Down
2 changes: 1 addition & 1 deletion crates/core_types/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ impl From<&Duration> for Period {
/// Debug: Iso8601(2018-10-11T03:23:38+00:00)
///
/// More info on the relevant [wikipedia article](https://en.wikipedia.org/wiki/ISO_8601).
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, DefaultJson)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, DefaultJson, Copy)]
pub struct Iso8601(DateTime<FixedOffset>);

/// Infallible conversions into and from an Iso8601. The only infallible ways to create an Iso8601
Expand Down
3 changes: 2 additions & 1 deletion crates/hdk/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ pub use crate::{
entry::{entry_type::EntryType, Entry},
error::HolochainError,
link::LinkMatch,
network::query::{Pagination, SortOrder},
network::query::{Pagination, SizePagination, SortOrder, TimePagination},
time::Iso8601,
},
holochain_json_api::{error::JsonError, json::JsonString},
holochain_persistence_api::cas::content::{Address, AddressableContent},
Expand Down
5 changes: 2 additions & 3 deletions doc/holochain_101/src/links/get_links.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ Get Links allows the zome developer to query links from the DHT. The call accept
`Timeout` : The timeout variable on the options specifies how long the query process should wait befor a response before it timesout
`LinksStatusRequest` : This is a variable in which you can specify 3 modes, `All`,`Live`,`Delete`. This allows you to query the links based on crud_status in which `All` will return everything will `Live` will only return live links and `Delete` as such.
`Headers`: boolean value which if set to true indicates that the link headers should also be returned.```
`Pagination`: The pagination type has two variables which are page size and page number. These describe the page size which divides the links into pages and the page number
which describes the page that we want to get.
'Sort Order' : Allows get_links to define which order `Ascending` or `Descending` the links should be returned in
`Pagination`: The pagination type has two variants which are `Size` and `Time` These variants allow the user to paginate based on choosing pages and specifying page size, or by specifying a point time and specifying a limit of the number of entries (based on the timestamp in the entry header) to return from that point.
`Sort Order` : Allows get_links to define which order `Ascending` or `Descending` the links should be returned in

# Link Results

Expand Down