Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

Commit

Permalink
feat: Publish name record from gateway periodically. (#334)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantell authored May 5, 2023
1 parent 3b0663a commit fc5e42f
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 50 deletions.
1 change: 1 addition & 0 deletions rust/noosphere-cli/src/native/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ impl Workspace {
/// Given a mime, infer its file extension
pub async fn infer_file_extension(&self, content_type: ContentType) -> Option<String> {
match content_type {
ContentType::Text => Some("txt".into()),
ContentType::Subtext => Some("subtext".into()),
ContentType::Sphere => Some("sphere".into()),
ContentType::Bytes => None,
Expand Down
127 changes: 83 additions & 44 deletions rust/noosphere-cli/tests/peer_to_peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@ use noosphere_storage::{BlockStoreRetry, MemoryStore, UcanStore};
use std::{net::TcpListener, sync::Arc, time::Duration};

use noosphere_cli::native::{
commands::{key::key_create, sphere::sphere_create},
commands::{config::config_set, key::key_create, sphere::sphere_create},
workspace::Workspace,
ConfigSetCommand,
};
use noosphere_core::{data::Did, tracing::initialize_tracing};
use noosphere_gateway::{start_gateway, GatewayScope};
use noosphere_ns::{helpers::NameSystemNetwork, server::start_name_system_api_server};
use noosphere_ns::{
helpers::NameSystemNetwork,
server::{start_name_system_api_server, HttpClient},
NameResolver,
};
use noosphere_sphere::{
HasMutableSphereContext, HasSphereContext, SphereContentWrite, SpherePetnameRead,
SpherePetnameWrite, SphereSync,
};
use tokio::{sync::Mutex, task::JoinHandle};
use ucan::store::UcanJwtStore;
use url::Url;

async fn start_gateway_for_workspace(
Expand Down Expand Up @@ -62,18 +66,32 @@ async fn start_gateway_for_workspace(
Ok((gateway_url, join_handle))
}

async fn start_name_system_server<S: UcanJwtStore + Clone + 'static>(
_store: S,
listener: TcpListener,
) -> Result<JoinHandle<()>> {
Ok(tokio::spawn(async move {
// TODO(#267) pass in IpfsStore rather than `None` here once validating
let mut network = NameSystemNetwork::generate::<S>(2, None).await.unwrap();
let node = network.nodes_mut().pop().unwrap();
start_name_system_api_server(Arc::new(Mutex::new(node)), listener)
.await
.unwrap();
}))
async fn start_name_system_server(ipfs_url: &Url) -> Result<(JoinHandle<()>, Url)> {
// TODO(#267)
let use_validation = false;
let store = if use_validation {
let inner = MemoryStore::default();
let inner = IpfsStore::new(inner, Some(KuboClient::new(ipfs_url).unwrap()));
let inner = BlockStoreRetry::new(inner, 5u32, Duration::new(1, 0));
let inner = UcanStore(inner);
Some(inner)
} else {
None
};
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let address = listener.local_addr().unwrap();
let url = Url::parse(format!("http://{}:{}", address.ip(), address.port()).as_str()).unwrap();

Ok((
tokio::spawn(async move {
let mut network = NameSystemNetwork::generate(2, store).await.unwrap();
let node = network.nodes_mut().pop().unwrap();
start_name_system_api_server(Arc::new(Mutex::new(node)), listener)
.await
.unwrap();
}),
url,
))
}

#[cfg(feature = "test_kubo")]
Expand All @@ -82,20 +100,7 @@ async fn gateway_publishes_and_resolves_petnames_configured_by_the_client() {
initialize_tracing(None);

let ipfs_url = Url::parse("http://127.0.0.1:5001").unwrap();

let ns_listener = TcpListener::bind("127.0.0.1:0").unwrap();
let ns_address = ns_listener.local_addr().unwrap();
let ns_url =
Url::parse(format!("http://{}:{}", ns_address.ip(), ns_address.port()).as_str()).unwrap();
let ns_db = {
let inner = MemoryStore::default();
let inner = IpfsStore::new(inner, Some(KuboClient::new(&ipfs_url).unwrap()));
let inner = BlockStoreRetry::new(inner, 5u32, Duration::new(1, 0));
let inner = UcanStore(inner);
inner
};

let ns_task = start_name_system_server(ns_db, ns_listener).await.unwrap();
let (ns_task, ns_url) = start_name_system_server(&ipfs_url).await.unwrap();

let (gateway_workspace, _gateway_temporary_directories) = Workspace::temporary().unwrap();
let (client_workspace, _client_temporary_directories) = Workspace::temporary().unwrap();
Expand Down Expand Up @@ -135,6 +140,29 @@ async fn gateway_publishes_and_resolves_petnames_configured_by_the_client() {
sphere_create(third_party_gateway_key_name, &third_party_gateway_workspace)
.await
.unwrap();
let client_identity = client_workspace.sphere_identity().await.unwrap();

config_set(
ConfigSetCommand::Counterpart {
did: client_identity.clone().into(),
},
&gateway_workspace,
)
.await
.unwrap();

config_set(
ConfigSetCommand::Counterpart {
did: third_party_client_workspace
.sphere_identity()
.await
.unwrap()
.into(),
},
&third_party_gateway_workspace,
)
.await
.unwrap();

let (gateway_url, gateway_task) = start_gateway_for_workspace(
&gateway_workspace,
Expand Down Expand Up @@ -222,31 +250,42 @@ async fn gateway_publishes_and_resolves_petnames_configured_by_the_client() {
third_party_gateway_task.abort();
});
client_task.await.unwrap();

// Restart gateway and name system, ensuring republishing occurs
let (ns_task, ns_url) = start_name_system_server(&ipfs_url).await.unwrap();
let ns_client = HttpClient::new(ns_url.clone()).await.unwrap();
assert!(
ns_client.resolve(&client_identity).await.unwrap().is_none(),
"new name system does not contain client identity"
);

let (_gateway_url, gateway_task) = start_gateway_for_workspace(
&gateway_workspace,
&client_workspace.sphere_identity().await.unwrap(),
&ipfs_url,
&ns_url,
)
.await
.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;
assert!(
ns_client.resolve(&client_identity).await.unwrap().is_some(),
"the gateway republishes records on start."
);
gateway_task.abort();
ns_task.abort();
}

#[cfg(feature = "test_kubo")]
#[tokio::test]
async fn traverse_spheres_and_read_content_via_noosphere_gateway_via_ipfs() {
use noosphere_cli::native::commands::config::config_set;
use noosphere_cli::native::ConfigSetCommand;
use noosphere_sphere::SphereContentRead;
use tokio::io::AsyncReadExt;
initialize_tracing(None);

let ipfs_url = Url::parse("http://127.0.0.1:5001").unwrap();

let ns_listener = TcpListener::bind("127.0.0.1:0").unwrap();
let ns_address = ns_listener.local_addr().unwrap();
let ns_url =
Url::parse(format!("http://{}:{}", ns_address.ip(), ns_address.port()).as_str()).unwrap();
let ns_db = {
let inner = MemoryStore::default();
let inner = IpfsStore::new(inner, Some(KuboClient::new(&ipfs_url).unwrap()));
let inner = BlockStoreRetry::new(inner, 5u32, Duration::new(1, 0));
let inner = UcanStore(inner);
inner
};
let ns_task = start_name_system_server(ns_db, ns_listener).await.unwrap();
let (ns_task, ns_url) = start_name_system_server(&ipfs_url).await.unwrap();

let (gateway_workspace, _gateway_temporary_directories) = Workspace::temporary().unwrap();
let (client_workspace, _client_temporary_directories) = Workspace::temporary().unwrap();
Expand Down
1 change: 1 addition & 0 deletions rust/noosphere-core/src/data/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ impl TryBundle for MemoIpld {
Some(value) => {
match ContentType::from_str(&value)? {
ContentType::Subtext
| ContentType::Text
| ContentType::Bytes
| ContentType::Json
| ContentType::Cbor => {
Expand Down
3 changes: 3 additions & 0 deletions rust/noosphere-core/src/data/headers/content_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{convert::Infallible, fmt::Display, str::FromStr};

#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
pub enum ContentType {
Text,
Subtext,
Sphere,
Bytes,
Expand All @@ -13,6 +14,7 @@ pub enum ContentType {
impl Display for ContentType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let value = match self {
ContentType::Text => "text/plain",
ContentType::Subtext => "text/subtext",
ContentType::Sphere => "noo/sphere",
ContentType::Bytes => "raw/bytes",
Expand All @@ -30,6 +32,7 @@ impl FromStr for ContentType {

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"text/plain" => ContentType::Text,
"text/subtext" => ContentType::Subtext,
"noo/sphere" => ContentType::Sphere,
"raw/bytes" => ContentType::Bytes,
Expand Down
2 changes: 2 additions & 0 deletions rust/noosphere-gateway/src/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use noosphere_core::tracing::initialize_tracing;

#[derive(Clone, Debug)]
pub struct GatewayScope {
/// Identity of gateway sphere.
pub identity: Did,
/// Identity of a managed sphere that is being reflected by gateway sphere.
pub counterpart: Did,
}

Expand Down
Loading

0 comments on commit fc5e42f

Please sign in to comment.