Skip to main content

surrealdb_server/
lib.rs

1//! Library entrypoints for embedding SurrealDB server inside another Rust application.
2//! Exposes the same init() used by the `surreal` binary so external apps can
3//! start SurrealDB within their own `main()`.
4//!
5//! <section class="warning">
6//! <h3>Unstable!</h3>
7//! This crate is <b>SurrealDB internal API</b>. It does not adhere to SemVer and its API is
8//! free to change and break code even between patch versions. If you are looking for a stable
9//! interface to the SurrealDB library please have a look at
10//! <a href="https://crates.io/crates/surrealdb">the Rust SDK</a>.
11//! </section>
12
13// Temporarily allow deprecated items until version 3.0 for backward compatibility
14#![allow(deprecated)]
15#![deny(clippy::mem_forget)]
16
17#[macro_use]
18extern crate tracing;
19
20mod cli;
21mod cnf;
22mod dbs;
23mod env;
24#[cfg(feature = "graphql")]
25mod gql;
26/// Make `ntw` public so embedders can access RouterFactory and related networking definitions
27/// when running SurrealDB as a library.
28pub mod ntw;
29/// Make `rpc` public so embedders can access RpcState and related router definitions
30/// when running SurrealDB as a library.
31pub mod rpc;
32mod telemetry;
33
34use std::future::Future;
35use std::process::ExitCode;
36
37pub use cli::{Config, ConfigCheck, ConfigCheckRequirements};
38/// Re-export `RouterFactory` for convenience so embedders can `use surreal::RouterFactory`.
39#[doc(inline)]
40pub use ntw::RouterFactory;
41/// Re-export `RpcState` for convenience so embedders can `use surreal::RpcState`.
42#[doc(inline)]
43pub use rpc::RpcState;
44#[doc(inline)]
45pub use surrealdb as sdk;
46/// Re-export `core` for convenience so embedders can `use surreal::core::...`.
47#[doc(inline)]
48pub use surrealdb_core as core;
49use surrealdb_core::buc::BucketStoreProvider;
50use surrealdb_core::kvs::TransactionBuilderFactory;
51
52// Re-export the core crate in the same path used across internal modules
53// so that `crate::core::...` keeps working when used as a library target.
54
55/// Initialize SurrealDB CLI/server with the same behavior as the `surreal` binary.
56/// This spins up a Tokio runtime with a larger stack size and then runs the CLI
57/// entrypoint (which starts the server when the `start` subcommand is used).
58///
59/// # Parameters
60/// - `composer`: A composer implementing the required traits for dependency injection.
61///
62/// # Generic parameters
63/// - `C`: A composer type that implements:
64///   - `TransactionBuilderFactory` (selects/validates the datastore backend)
65///   - `RouterFactory` (constructs the HTTP router)
66///   - `ConfigCheck` (validates configuration before initialization)
67pub fn init<C: TransactionBuilderFactory + RouterFactory + ConfigCheck + BucketStoreProvider>(
68	composer: C,
69) -> ExitCode {
70	with_enough_stack(cli::init::<C>(composer))
71}
72
73/// Rust's default thread stack size of 2MiB doesn't allow sufficient recursion depth
74/// for SurrealDB's query parser and execution engine. This function creates a Tokio
75/// runtime with a larger stack size configured via `cnf::RUNTIME_STACK_SIZE`.
76fn with_enough_stack(fut: impl Future<Output = ExitCode> + Send) -> ExitCode {
77	// Start a Tokio runtime with custom configuration
78	let runtime = tokio::runtime::Builder::new_multi_thread()
79		.enable_all()
80		.max_blocking_threads(*cnf::RUNTIME_MAX_BLOCKING_THREADS)
81		.worker_threads(*cnf::RUNTIME_WORKER_THREADS)
82		.thread_stack_size(*cnf::RUNTIME_STACK_SIZE)
83		.thread_name("surrealdb-worker")
84		// When a thread is parked, ensure that local memory
85		// tracking is flushed to the global tracking counter.
86		.on_thread_park(|| core::mem::ALLOC.flush_local_allocations())
87		// When a thread is shutdown, ensure that local memory
88		// tracking is flushed to the global tracking counter.
89		.on_thread_stop(|| core::mem::ALLOC.flush_local_allocations())
90		// Build the runtime
91		.build();
92	// Check the success of the runtime creation
93	match runtime {
94		Ok(r) => r.block_on(fut),
95		Err(e) => {
96			// The runtime creation failed (e.g. insufficient system resources)
97			error!("Failed to build runtime: {e}");
98			ExitCode::FAILURE
99		}
100	}
101}