use ngdb::{DatabaseConfig, Ref, Result, Storable, ngdb};
use std::sync::Arc;
use std::thread;
#[ngdb("users")]
struct User {
id: u64,
name: String,
email: String,
}
impl Storable for User {
type Key = u64;
fn key(&self) -> Self::Key {
self.id
}
}
#[ngdb("posts")]
struct Post {
id: u64,
title: String,
content: String,
author: Ref<User>,
}
impl Storable for Post {
type Key = u64;
fn key(&self) -> Self::Key {
self.id
}
}
fn main() -> Result<()> {
let db = Arc::new(
DatabaseConfig::new("./data/threadsafe_refs_example")
.create_if_missing(true)
.add_column_family("users")
.add_column_family("posts")
.open()?,
);
let alice = User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
alice.save(&db)?;
let bob = User {
id: 2,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
};
bob.save(&db)?;
let post1 = Post {
id: 1,
title: "Introduction to NGDB".to_string(),
content: "NGDB is a high-performance RocksDB wrapper...".to_string(),
author: Ref::new(1),
};
post1.save(&db)?;
let post2 = Post {
id: 2,
title: "Advanced NGDB Features".to_string(),
content: "Learn about transactions, replication...".to_string(),
author: Ref::new(2),
};
post2.save(&db)?;
let mut handles = vec![];
for i in 1..=2 {
let db_clone = Arc::clone(&db);
let handle = thread::spawn(move || -> Result<()> {
let posts = Post::collection(&db_clone)?;
let post = posts.get(&i)?.unwrap();
let author = post.author.get(&db_clone)?;
println!(
"[Thread {:?}] Post {}: '{}' by {}",
thread::current().id(),
i,
post.title,
author.name
);
Ok(())
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap()?;
}
let posts = Post::collection(&db)?;
let post = posts.get(&1)?.unwrap();
let _ = post.author.get(&db)?;
let post_arc = Arc::new(post);
let mut handles = vec![];
for i in 0..5 {
let db_clone = Arc::clone(&db);
let post_clone = Arc::clone(&post_arc);
let handle = thread::spawn(move || -> Result<()> {
let author = post_clone.author.get(&db_clone)?;
println!("[Thread {}] Author: {}", i, author.name);
Ok(())
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap()?;
}
let post_ids = vec![1, 2];
let chunk_size = 1;
let mut handles = vec![];
for chunk in post_ids.chunks(chunk_size) {
let db_clone = Arc::clone(&db);
let chunk = chunk.to_vec();
let handle = thread::spawn(move || -> Result<Vec<String>> {
let posts = Post::collection(&db_clone)?;
let mut results = Vec::new();
for id in chunk {
if let Some(post) = posts.get(&id)? {
let author = post.author.get(&db_clone)?;
let summary = format!("{} by {}", post.title, author.name);
results.push(summary);
}
}
Ok(results)
});
handles.push(handle);
}
for handle in handles {
let results = handle.join().unwrap()?;
for summary in results {
println!(" - {}", summary);
}
}
use std::sync::mpsc;
let (tx, rx) = mpsc::channel();
let num_workers = 3;
let mut workers = vec![];
for worker_id in 0..num_workers {
let db_clone = Arc::clone(&db);
let tx_clone = tx.clone();
let worker = thread::spawn(move || {
let posts = Post::collection(&db_clone).unwrap();
for post_id in 1..=2 {
if post_id % num_workers == worker_id {
if let Ok(Some(post)) = posts.get(&post_id) {
let author = post.author.get(&db_clone).unwrap();
let result = format!(
"[Worker {}] Processed: '{}', Author: {}",
worker_id, post.title, author.name
);
tx_clone.send(result).unwrap();
}
}
}
});
workers.push(worker);
}
drop(tx);
for received in rx {
println!(" {}", received);
}
for worker in workers {
worker.join().unwrap();
}
Ok(())
}