Skip to content
Draft
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
11 changes: 11 additions & 0 deletions .github/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,14 @@ html
https
www
faq
EmbeddedConfig
PathBuf
prototyping
Embedded
Spawns
Unix
cleans
FalkorResult
FalkorClientBuilder
FalkorConnectionInfo
EmbeddedServer
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ strum = { version = "0.27.1", default-features = false, features = ["std", "deri
thiserror = "2.0.12"
tokio = { version = "1.45.1", default-features = false, features = ["macros", "sync", "rt-multi-thread"], optional = true }
tracing = { version = "0.1.41", default-features = false, features = ["std", "attributes"], optional = true }
which = { version = "7.0.1", optional = true }

[dev-dependencies]
approx = "0.5.1"
Expand All @@ -39,9 +40,15 @@ tokio-rustls = ["tokio", "redis/tokio-rustls-comp"]

tracing = ["dep:tracing"]

embedded = ["dep:which"]

[[example]]
name = "basic_usage"

[[example]]
name = "async_api"
required-features = ["tokio"]

[[example]]
name = "embedded_usage"
required-features = ["embedded"]
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,60 @@ falkordb = { version = "0.1.10", features = ["tracing"] }

Note that different functions use different filtration levels, to avoid spamming your tests, be sure to enable the
correct level as you desire it.

### Embedded FalkorDB Server

This client supports running an embedded FalkorDB server, which is useful for:
- Testing without external dependencies
- Embedded applications
- Quick prototyping and development

To use the embedded feature, enable it in your `Cargo.toml`:

```toml
falkordb = { version = "0.1.10", features = ["embedded"] }
```

#### Requirements

- `redis-server` must be installed and available in PATH (or you can specify a custom path)
- `falkordb.so` module must be installed (or you can specify a custom path)

You can install these from:
- Redis: https://github.com/redis/redis
- FalkorDB: https://github.com/falkordb/falkordb

#### Usage Example

```rust
use falkordb::{EmbeddedConfig, FalkorClientBuilder, FalkorConnectionInfo};

// Create an embedded configuration with defaults
let embedded_config = EmbeddedConfig::default();

// Or customize the configuration:
// let embedded_config = EmbeddedConfig {
// redis_server_path: Some(PathBuf::from("/path/to/redis-server")),
// falkordb_module_path: Some(PathBuf::from("/path/to/falkordb.so")),
// db_dir: Some(PathBuf::from("/tmp/my_falkordb")),
// ..Default::default()
// };

// Build a client with embedded FalkorDB
let client = FalkorClientBuilder::new()
.with_connection_info(FalkorConnectionInfo::Embedded(embedded_config))
.build()
.expect("Failed to build client");

// Use the client normally
let mut graph = client.select_graph("social");
graph.query("CREATE (:Person {name: 'Alice', age: 30})").execute()?;

// The embedded server will be automatically shut down when the client is dropped
```

The embedded server:
- Spawns a `redis-server` process with the FalkorDB module loaded
- Uses Unix socket for communication (no network port)
- Automatically cleans up when the client is dropped
- Can be configured with custom paths, database directory, and socket location
109 changes: 109 additions & 0 deletions examples/embedded_usage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright FalkorDB Ltd. 2023 - present
* Licensed under the MIT License.
*/

//! Example demonstrating the embedded FalkorDB server feature.
//!
//! This example shows how to use FalkorDB with an embedded Redis server
//! that has the FalkorDB module loaded. This is useful for:
//! - Testing without external dependencies
//! - Embedded applications
//! - Quick prototyping
//!
//! # Requirements
//! - redis-server must be installed and available in PATH (or specify path in EmbeddedConfig)
//! - falkordb.so module must be installed (or specify path in EmbeddedConfig)
//!
//! # Running this example
//! ```bash
//! cargo run --example embedded_usage --features embedded
//! ```

use falkordb::{EmbeddedConfig, FalkorClientBuilder, FalkorConnectionInfo, FalkorResult};

fn main() -> FalkorResult<()> {
println!("Starting embedded FalkorDB example...");

// Create an embedded configuration
// This will use defaults: redis-server from PATH, falkordb.so from common locations
let embedded_config = EmbeddedConfig::default();

// You can also customize the configuration:
// let embedded_config = EmbeddedConfig {
// redis_server_path: Some(PathBuf::from("/path/to/redis-server")),
// falkordb_module_path: Some(PathBuf::from("/path/to/falkordb.so")),
// db_dir: Some(PathBuf::from("/tmp/my_falkordb")),
// db_filename: "mydb.rdb".to_string(),
// socket_path: Some(PathBuf::from("/tmp/falkordb.sock")),
// start_timeout: Duration::from_secs(10),
// };

println!("Creating client with embedded FalkorDB server...");

// Build a client with embedded FalkorDB
let client = FalkorClientBuilder::new()
.with_connection_info(FalkorConnectionInfo::Embedded(embedded_config))
.build()?;

println!("Connected to embedded FalkorDB server!");

// Now use the client normally
let mut graph = client.select_graph("social");

// Create some nodes
println!("Creating nodes...");
graph
.query("CREATE (:Person {name: 'Alice', age: 30})")
.execute()?;
graph
.query("CREATE (:Person {name: 'Bob', age: 25})")
.execute()?;
graph
.query("CREATE (:Person {name: 'Charlie', age: 35})")
.execute()?;

// Create relationships
println!("Creating relationships...");
graph
.query(
"MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'}) CREATE (a)-[:KNOWS]->(b)",
)
.execute()?;
graph
.query(
"MATCH (b:Person {name: 'Bob'}), (c:Person {name: 'Charlie'}) CREATE (b)-[:KNOWS]->(c)",
)
.execute()?;

// Query the graph
println!("\nQuerying the graph:");
let result = graph
.query("MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age")
.execute()?;

println!("Found {} results:", result.data.len());
for row in result.data {
println!(" {:?}", row);
}

// Query with relationships
println!("\nQuerying relationships:");
let result = graph
.query("MATCH (a:Person)-[:KNOWS]->(b:Person) RETURN a.name, b.name")
.execute()?;

println!("Found {} relationships:", result.data.len());
for row in result.data {
println!(" {:?}", row);
}

// Clean up
println!("\nDeleting graph...");
graph.delete()?;

println!("Example completed successfully!");
println!("The embedded server will be automatically shut down when the client is dropped.");

Ok(())
}
Loading