Skip to content

Commit

Permalink
Refactor for storage provider
Browse files Browse the repository at this point in the history
  • Loading branch information
cafca committed May 17, 2022
1 parent 591c6a0 commit d0fc7c7
Showing 1 changed file with 30 additions and 55 deletions.
85 changes: 30 additions & 55 deletions aquadoggo/src/graphql/client/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

use async_graphql::{Context, Error, Object, Result, SimpleObject};
use bamboo_rs_core_ed25519_yasmf::entry::is_lipmaa_required as is_skiplink_required;
use p2panda_rs::entry::SeqNum;
use p2panda_rs::document::DocumentId;
use p2panda_rs::hash::Hash;
use p2panda_rs::identity::Author;
use p2panda_rs::storage_provider::traits::StorageProvider;

use crate::db::models::{Entry, Log};
use crate::db::provider::SqlStorage;
use crate::db::Pool;
use crate::rpc::{EntryArgsRequest, EntryArgsResponse};

//
#[derive(SimpleObject)]
pub struct EntryArgs {
pub log_id: String,
Expand All @@ -17,6 +20,17 @@ pub struct EntryArgs {
pub skiplink: Option<String>,
}

impl From<EntryArgsResponse> for EntryArgs {
fn from(value: EntryArgsResponse) -> Self {
EntryArgs {
log_id: value.log_id.as_u64().to_string(),
seq_num: value.seq_num.as_u64().to_string(),
backlink: value.entry_hash_backlink.map(|hash| hash.to_string()),
skiplink: value.entry_hash_skiplink.map(|hash| hash.to_string()),
}
}
}

#[derive(Default, Debug, Copy, Clone)]
/// The GraphQL root for the client api that p2panda clients can use to connect to a node.
pub struct ClientRoot;
Expand All @@ -38,69 +52,30 @@ impl ClientRoot {
)]
document_id_param: Option<String>,
) -> Result<EntryArgs> {
let public_key = Author::new(&public_key_param)?;
// Parse and validate parameters
let document_id = match document_id_param {
Some(value) => Some(Hash::new(&value)?),
Some(val) => Some(val.parse::<DocumentId>()?),
None => None,
};
let args = EntryArgsRequest {
author: Author::new(&public_key_param)?,
document: document_id,
};

// Get database connection pool
// Prepare database connection
let pool = ctx.data::<Pool>().map_err(|err| Error::from(err))?;
let provider = SqlStorage {
pool: pool.to_owned(),
};

// Determine log_id for this document. If this is the very first operation in the document
// graph, the `document` value is None and we will return the next free log id
let log_id = Log::find_document_log_id(&pool, &public_key, document_id.as_ref()).await?;

// Determine backlink and skiplink hashes for the next entry. To do this we need the latest
// entry in this log
let entry_latest = Entry::latest(&pool, &public_key, &log_id).await?;

match entry_latest {
// An entry was found which serves as the backlink for the upcoming entry
Some(mut entry_backlink) => {
// Determine skiplink ("lipmaa"-link) entry in this log
let skiplink = determine_skiplink(pool.clone(), &entry_backlink).await?;

Ok(EntryArgs {
log_id: log_id.as_u64().to_string(),
seq_num: entry_backlink.seq_num.next().unwrap().as_u64().to_string(),
backlink: Some(entry_backlink.entry_hash.as_str().into()),
skiplink: skiplink.map(|h| h.as_str().into()),
})
}
// No entry was given yet, we can assume this is the beginning of the log
None => Ok(EntryArgs {
log_id: log_id.as_u64().to_string(),
seq_num: SeqNum::default().as_u64().to_string(),
backlink: None,
skiplink: None,
}),
match provider.get_entry_args(&args).await {
Ok(entry_args) => Ok(entry_args.into()),
Err(_) => Err(Error::new("Graphql gone wrong")),
// Err(err) => Err(Error::from(err)),
}
}
}

/// Determine skiplink entry hash for entry in this log, return `None` when no skiplink is
/// required for the next entry.
pub async fn determine_skiplink(pool: Pool, entry: &Entry) -> Result<Option<Hash>> {
let next_seq_num = entry.seq_num.clone().next().unwrap();

// Unwrap as we know that an skiplink exists as soon as previous entry is given
let skiplink_seq_num = next_seq_num.skiplink_seq_num().unwrap();

// Check if skiplink is required and return hash if so
let entry_skiplink_hash = if is_skiplink_required(next_seq_num.as_u64()) {
let skiplink_entry =
Entry::at_seq_num(&pool, &entry.author, &entry.log_id, &skiplink_seq_num)
.await?
.unwrap();
Some(skiplink_entry.entry_hash)
} else {
None
};

Ok(entry_skiplink_hash)
}

#[cfg(test)]
mod tests {
use serde_json::json;
Expand Down

0 comments on commit d0fc7c7

Please sign in to comment.