Skip to content

Commit 984e9d5

Browse files
authored
spacetimedb-runtime crate split into spacetimedb-runtime-core (#5638)
# Description of Changes This is mostly code motion to add `spacetimedb-runtime-core` as a new `no_std` crate. The intent is for `runtime-core` to host custom runtime implementations/interfaces. The first implementation moved there is DST’s `sim` module, gated behind the `sim` feature. Code should continue to depend on `spacetimedb-runtime`, not `spacetimedb-runtime-core` directly. `spacetimedb-runtime` remains the stable facade: it exposes the public runtime boundary and can select different runtime implementations depending on build configuration. # API and ABI breaking changes NA # Expected complexity level and risk 1 # Testing Not required.
1 parent 8790769 commit 984e9d5

16 files changed

Lines changed: 107 additions & 94 deletions

File tree

Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ members = [
2828
"crates/primitives",
2929
"crates/query",
3030
"crates/runtime",
31+
"crates/runtime-core",
3132
"crates/sats",
3233
"crates/schema",
3334
"crates/smoketests",
@@ -152,6 +153,7 @@ spacetimedb-primitives = { path = "crates/primitives", version = "=2.7.1" }
152153
spacetimedb-query = { path = "crates/query", version = "=2.7.1" }
153154
spacetimedb-query-builder = { path = "crates/query-builder", version = "=2.7.1" }
154155
spacetimedb-runtime = { path = "crates/runtime", version = "=2.7.1" }
156+
spacetimedb-runtime-core = { path = "crates/runtime-core", version = "=2.7.1" }
155157
spacetimedb-sats = { path = "crates/sats", version = "=2.7.1" }
156158
spacetimedb-schema = { path = "crates/schema", version = "=2.7.1" }
157159
spacetimedb-snapshot = { path = "crates/snapshot", version = "=2.7.1" }

crates/runtime-core/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "spacetimedb-runtime-core"
3+
version.workspace = true
4+
edition.workspace = true
5+
license-file = "LICENSE"
6+
description = "Portable no_std runtime core utilities for SpacetimeDB"
7+
rust-version.workspace = true
8+
9+
[lints]
10+
workspace = true
11+
12+
[features]
13+
default = []
14+
sim = ["dep:async-task", "dep:spin"]
15+
16+
[dependencies]
17+
async-task = { version = "4.4", default-features = false, optional = true }
18+
spin = { version = "0.9", default-features = false, features = ["mutex", "spin_mutex"], optional = true }

crates/runtime-core/LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../licenses/BSL.txt

crates/runtime-core/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![no_std]
2+
3+
#[cfg(feature = "sim")]
4+
extern crate alloc;
5+
#[cfg(test)]
6+
extern crate std;
7+
8+
#[cfg(feature = "sim")]
9+
pub mod sim;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::sim::Runtime;
1+
use super::Runtime;
22

33
/// Probabilistic fault-injection helpers for simulation code.
44
///

crates/runtime/src/sim/executor/mod.rs renamed to crates/runtime-core/src/sim/executor/mod.rs

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use core::{
1010

1111
use spin::Mutex;
1212

13-
use crate::sim::{time::TimeHandle, Rng};
13+
use super::{time::TimeHandle, Rng};
1414

1515
mod task;
1616
use task::Abortable;
@@ -220,22 +220,26 @@ impl Runtime {
220220
}
221221

222222
#[allow(dead_code)]
223-
pub(crate) fn enable_determinism_log(&self) {
223+
#[doc(hidden)]
224+
pub fn enable_determinism_log(&self) {
224225
self.executor.rng.enable_determinism_log();
225226
}
226227

227228
#[allow(dead_code)]
228-
pub(crate) fn enable_determinism_check(&self, log: crate::sim::DeterminismLog) {
229+
#[doc(hidden)]
230+
pub fn enable_determinism_check(&self, log: super::DeterminismLog) {
229231
self.executor.rng.enable_determinism_check(log);
230232
}
231233

232234
#[allow(dead_code)]
233-
pub(crate) fn take_determinism_log(&self) -> Option<crate::sim::DeterminismLog> {
235+
#[doc(hidden)]
236+
pub fn take_determinism_log(&self) -> Option<super::DeterminismLog> {
234237
self.executor.rng.take_determinism_log()
235238
}
236239

237240
#[allow(dead_code)]
238-
pub(crate) fn finish_determinism_check(&self) -> Result<(), alloc::string::String> {
241+
#[doc(hidden)]
242+
pub fn finish_determinism_check(&self) -> Result<(), alloc::string::String> {
239243
self.executor.rng.finish_determinism_check()
240244
}
241245
}
@@ -306,7 +310,7 @@ impl Handle {
306310
}
307311

308312
/// Create a future that becomes ready after `duration` of virtual time.
309-
pub fn sleep(&self, duration: Duration) -> crate::sim::time::Sleep {
313+
pub fn sleep(&self, duration: Duration) -> super::time::Sleep {
310314
self.executor.time.sleep(duration)
311315
}
312316

@@ -315,7 +319,7 @@ impl Handle {
315319
&self,
316320
duration: Duration,
317321
future: impl Future<Output = T>,
318-
) -> Result<T, crate::sim::time::TimeoutElapsed> {
322+
) -> Result<T, super::time::TimeoutElapsed> {
319323
self.executor.time.timeout(duration, future).await
320324
}
321325

@@ -645,7 +649,7 @@ impl Receiver {
645649
#[cfg(test)]
646650
mod tests {
647651
use std::sync::{
648-
atomic::{AtomicBool, AtomicUsize, Ordering},
652+
atomic::{AtomicUsize, Ordering},
649653
Arc,
650654
};
651655

@@ -734,13 +738,12 @@ mod tests {
734738
assert_eq!(err, JoinError);
735739
}
736740

737-
#[cfg(feature = "simulation")]
738741
#[test]
739-
fn sim_std_block_on_can_spawn_local_task_with_explicit_handle() {
742+
fn block_on_can_spawn_local_task_with_explicit_handle() {
740743
let mut runtime = Runtime::new(5);
741744
let handle = runtime.handle();
742745
let node = handle.create_node().name("local").build();
743-
let value = crate::sim_std::block_on(&mut runtime, async move {
746+
let value = runtime.block_on(async move {
744747
let captured = std::rc::Rc::new(17);
745748
node.spawn_local(async move {
746749
yield_now().await;
@@ -763,34 +766,4 @@ mod tests {
763766
assert_eq!(named.name(), Some("replica-1"));
764767
assert_ne!(unnamed.id(), named.id());
765768
}
766-
767-
#[cfg(feature = "simulation")]
768-
#[test]
769-
fn check_determinism_runs_future_twice() {
770-
static CALLS: AtomicUsize = AtomicUsize::new(0);
771-
CALLS.store(0, Ordering::SeqCst);
772-
773-
let value = crate::sim_std::check_determinism(3, || async {
774-
CALLS.fetch_add(1, Ordering::SeqCst);
775-
yield_now().await;
776-
13
777-
});
778-
779-
assert_eq!(value, 13);
780-
assert_eq!(CALLS.load(Ordering::SeqCst), 2);
781-
}
782-
783-
#[cfg(feature = "simulation")]
784-
#[test]
785-
#[should_panic(expected = "non-determinism detected")]
786-
fn check_determinism_rejects_different_scheduler_sequence() {
787-
static FIRST_RUN: AtomicBool = AtomicBool::new(true);
788-
FIRST_RUN.store(true, Ordering::SeqCst);
789-
790-
crate::sim_std::check_determinism(4, || async {
791-
if FIRST_RUN.swap(false, Ordering::SeqCst) {
792-
yield_now().await;
793-
}
794-
});
795-
}
796769
}

crates/runtime/src/sim/executor/task.rs renamed to crates/runtime-core/src/sim/executor/task.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ impl<T> JoinHandle<T> {
3838
}
3939

4040
/// Poll the underlying async_task::Task for its output.
41-
pub(crate) fn poll_join(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<T, JoinError>> {
41+
#[doc(hidden)]
42+
pub fn poll_join(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<T, JoinError>> {
4243
// async_task::Task implements Future. Polling it drives the wrapped
4344
// Abortable future inside the executor.
4445
Pin::new(&mut self.task).poll(cx)
@@ -96,8 +97,7 @@ impl fmt::Display for JoinError {
9697
}
9798
}
9899

99-
#[cfg(feature = "simulation")]
100-
impl std::error::Error for JoinError {}
100+
impl core::error::Error for JoinError {}
101101

102102
// Shared state between AbortHandle and Abortable.
103103
struct AbortState {
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ pub mod time;
66
pub use executor::{
77
yield_now, AbortHandle, Handle, JoinError, JoinHandle, Node, NodeBuilder, NodeId, Runtime, RuntimeConfig,
88
};
9-
pub(crate) use rng::DeterminismLog;
9+
#[doc(hidden)]
10+
pub use rng::DeterminismLog;
1011
pub use rng::{GlobalRng, Rng};
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub type Rng = GlobalRng;
99
/// The simulator owns one runtime-wide RNG handle and uses it for scheduler
1010
/// choices, probabilistic fault injection, and determinism checks. Hosted
1111
/// conveniences such as thread-local current-RNG access and libc random hooks
12-
/// live in `crate::sim_std`, not here.
12+
/// live in the hosted runtime facade, not here.
1313
#[derive(Clone, Debug)]
1414
pub struct GlobalRng {
1515
inner: Arc<Mutex<Inner>>,
@@ -143,21 +143,24 @@ impl GlobalRng {
143143
}
144144

145145
#[allow(dead_code)]
146-
pub(crate) fn enable_determinism_log(&self) {
146+
#[doc(hidden)]
147+
pub fn enable_determinism_log(&self) {
147148
let mut inner = self.inner.lock();
148149
inner.log = Some(Vec::new());
149150
inner.check = None;
150151
}
151152

152153
#[allow(dead_code)]
153-
pub(crate) fn enable_determinism_check(&self, log: DeterminismLog) {
154+
#[doc(hidden)]
155+
pub fn enable_determinism_check(&self, log: DeterminismLog) {
154156
let mut inner = self.inner.lock();
155157
inner.check = Some((log.0, 0));
156158
inner.log = None;
157159
}
158160

159161
#[allow(dead_code)]
160-
pub(crate) fn take_determinism_log(&self) -> Option<DeterminismLog> {
162+
#[doc(hidden)]
163+
pub fn take_determinism_log(&self) -> Option<DeterminismLog> {
161164
let mut inner = self.inner.lock();
162165
inner
163166
.log
@@ -167,7 +170,8 @@ impl GlobalRng {
167170
}
168171

169172
#[allow(dead_code)]
170-
pub(crate) fn finish_determinism_check(&self) -> Result<(), String> {
173+
#[doc(hidden)]
174+
pub fn finish_determinism_check(&self) -> Result<(), String> {
171175
let inner = self.inner.lock();
172176
if let Some((log, consumed)) = &inner.check
173177
&& *consumed != log.len()
@@ -183,7 +187,7 @@ impl GlobalRng {
183187
}
184188

185189
#[derive(Debug, Clone, Eq, PartialEq)]
186-
pub(crate) struct DeterminismLog(Vec<u8>);
190+
pub struct DeterminismLog(Vec<u8>);
187191

188192
fn probability_sample(value: u64, probability: f64) -> bool {
189193
if probability <= 0.0 {

0 commit comments

Comments
 (0)