Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
b971def
attempt at fixing the graph writing logic for windows
ljeub-pometry Nov 17, 2025
9b0d94f
fmt
ljeub-pometry Nov 17, 2025
3e578bb
It should never be possible for a graph to be de-cached while it is b…
ljeub-pometry Nov 18, 2025
ada3afb
fmt
ljeub-pometry Nov 18, 2025
fbde175
initial implementation of dirty path tracking
ljeub-pometry Dec 1, 2025
7805348
more validation
ljeub-pometry Dec 1, 2025
c0da91e
need to clean up dirty paths during validation
ljeub-pometry Dec 1, 2025
e5374aa
Refactor writing to disk such that it writes with the new folder stru…
ljeub-pometry Dec 8, 2025
a9f5c50
fix writing to empty graph folder
ljeub-pometry Dec 8, 2025
260b165
move a lot more of the logic to GraphFolder
ljeub-pometry Dec 9, 2025
f4e3cb8
fix zip encoding/decoding
ljeub-pometry Dec 10, 2025
4330632
all the tests compile
ljeub-pometry Dec 10, 2025
a275065
all features compile
ljeub-pometry Dec 11, 2025
1eb3018
move the python benchmarks so they don't always run
ljeub-pometry Dec 11, 2025
3f2a95d
make secondary_index the last argument so it doesn't become annoying
ljeub-pometry Dec 11, 2025
55cb6f6
improved error messages
ljeub-pometry Dec 11, 2025
42cff8e
need to get the graph before creating the new folder or the new path …
ljeub-pometry Dec 11, 2025
7ea994b
don't create arbitrarily deep paths when writing graphs
ljeub-pometry Dec 11, 2025
9ba4158
better error messages
ljeub-pometry Dec 11, 2025
b85412d
overwrite is handled internally, no need to call delete
ljeub-pometry Dec 11, 2025
756b1b6
fix doc strings
ljeub-pometry Dec 11, 2025
b669122
no more deserialize for Prop
ljeub-pometry Dec 12, 2025
7ae6376
load graph metadata from the parquet file instead
ljeub-pometry Dec 12, 2025
5c6ff6e
tidy up a lot of warnings
ljeub-pometry Dec 15, 2025
391c57b
fmt
ljeub-pometry Dec 15, 2025
775cedc
Merge db_v4 into fix/graphql_v4
ljeub-pometry Dec 16, 2025
3c259bf
tidy up and add more validation for relative paths
ljeub-pometry Dec 16, 2025
558dd7f
need to bring back Prop deserialisation for the WAL
ljeub-pometry Dec 17, 2025
253afb9
this reserve causes a race condition as it re-checks the count and is…
ljeub-pometry Dec 17, 2025
2606756
flat serialisation of Prop for working with arrow
ljeub-pometry Dec 17, 2025
82c8145
simplify serialisation for SerdeArrowArray
ljeub-pometry Dec 17, 2025
3ecf1a8
more refactoring of the graph path handling
ljeub-pometry Dec 19, 2025
d73c2da
avoid writing metadata without writing graph
ljeub-pometry Dec 19, 2025
5256ac0
is_reserved should not be true for files
ljeub-pometry Dec 19, 2025
3d716be
materialize_at only works with persistent storage
ljeub-pometry Dec 19, 2025
6da9ba7
need to write the metadata in decode_at variants
ljeub-pometry Dec 19, 2025
2ebbad9
load metadata correctly when storage is enabled and use cached graph …
ljeub-pometry Dec 19, 2025
8daaed8
fix send_graph
ljeub-pometry Dec 19, 2025
bdc611d
fix new_graph in graphql
ljeub-pometry Dec 19, 2025
6bfbced
improve error messages
ljeub-pometry Dec 19, 2025
597dab1
always use / in zip paths
ljeub-pometry Jan 5, 2026
40b55a8
fmt
ljeub-pometry Jan 5, 2026
c5d7e56
rearrange tests to ignore indexing/vectors
ljeub-pometry Jan 5, 2026
4055d76
look at .raph file instead
ljeub-pometry Jan 5, 2026
ec3a44f
tweak seed to get the old result as order of operations changed
ljeub-pometry Jan 5, 2026
5bd7429
hopefully more robust fast_rp test
ljeub-pometry Jan 5, 2026
8ebfef0
chore: apply tidy-public auto-fixes
github-actions[bot] Jan 5, 2026
8bd5ddd
update graph to new format
ljeub-pometry Jan 6, 2026
a7da5d3
no unzipping needed anymore
ljeub-pometry Jan 6, 2026
b79c7e5
some minor cleanup
ljeub-pometry Jan 6, 2026
d2eaa98
track io failure location
ljeub-pometry Jan 6, 2026
eb0049b
fix storage check
ljeub-pometry Jan 6, 2026
9158478
make sure all dirty paths are cleaned up properly
ljeub-pometry Jan 6, 2026
11b4b62
fix drop handling for storage-enabled graphs
ljeub-pometry Jan 6, 2026
2d02ab0
use send_graph instead of save to also test the storage
ljeub-pometry Jan 7, 2026
4fbc099
remove stray println!
ljeub-pometry Jan 7, 2026
313edb0
don't panic on errors
ljeub-pometry Jan 7, 2026
248953e
delete should remove the graph from cache
ljeub-pometry Jan 7, 2026
40a7d97
make sure load preserves the id type
ljeub-pometry Jan 7, 2026
10837ba
fmt
ljeub-pometry Jan 7, 2026
21da0be
try to fix the graphql benchmark workflow
ljeub-pometry Jan 7, 2026
9b6fc47
use send_graph to test storage
ljeub-pometry Jan 7, 2026
40d1ab6
add invalidation to make sure cached graphs are dropped before we del…
ljeub-pometry Jan 8, 2026
ad1ca09
rename disk_storage_enabled to disk_storage_path
ljeub-pometry Jan 8, 2026
680901d
rename inner metadata file to .meta and address remaining review comm…
ljeub-pometry Jan 8, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/bench-graphql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Run GraphQL benchmarks
run: cd graphql-bench && make bench-local
- name: Restore metadata file
run: git restore graphql-bench/data/apache/master/.raph # otherwise github-action-benchmark fails to create the commit
run: git restore graphql-bench/data/apache/master # otherwise github-action-benchmark fails to create the commit
- name: Print bench results
run: cat graphql-bench/output.json
- name: Store benchmark results from master branch
Expand Down
31 changes: 8 additions & 23 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,13 @@ build-all: rust-build

test-all: rust-test-all python-test

test-all-public: rust-test-all-public python-test-public

# Tidying

tidy: rust-fmt build-python stubs python-fmt

tidy-public: rust-fmt build-python-public stubs python-fmt

python-tidy: stubs python-fmt test-graphql-schema

check-pr: tidy-public test-all
check-pr: tidy test-all

gen-graphql-schema:
raphtory schema > raphtory-graphql/schema.graphql
Expand All @@ -31,7 +27,6 @@ test-graphql-schema: install-node-tools
npx graphql-schema-linter --rules fields-have-descriptions,types-have-descriptions raphtory-graphql/schema.graphql

# Utilities

activate-storage:
./scripts/activate_private_storage.py

Expand Down Expand Up @@ -71,13 +66,12 @@ run-graphql:
rust-test:
cargo test -q

rust-test-all: activate-storage
cargo nextest run --all --features=storage
rust-check:
cargo hack check --workspace --all-targets --each-feature --skip extension-module,default

rust-test-all-public:
rust-test-all: rust-check
cargo nextest run --all
cargo hack check --workspace --all-targets --each-feature --skip extension-module,default,storage


##########
# Python #
Expand All @@ -86,32 +80,23 @@ rust-test-all-public:
install-python:
cd python && maturin build && pip install ../target/wheels/*.whl

build-python-public: deactivate-storage
build-python:
cd python && maturin develop -r --extras=dev

build-python: activate-storage
cd python && maturin develop -r --features=storage --extras=dev
debug-python:
cd python && maturin develop --profile=debug --extras=dev

# Testing

python-test: activate-storage
cd python && tox run && tox run -e storage

python-test-public:
python-test:
cd python && tox run

python-fmt:
cd python && black .

debug-python-public: deactivate-storage
cd python && maturin develop --profile=debug

build-python-rtd:
cd python && maturin build --profile=build-fast && pip install ../target/wheels/*.whl

debug-python: activate-storage
cd python && maturin develop --features=storage,extension-module --extras=dev

########
# Docs #
########
Expand Down
18 changes: 13 additions & 5 deletions db4-graph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
};

use raphtory_api::core::{
entities::{self, properties::meta::Meta},
entities::{self, properties::meta::Meta, GidType},
input::input_node::InputNode,
};
use raphtory_core::{
Expand Down Expand Up @@ -149,9 +149,10 @@ impl<EXT: PersistentStrategy<NS = NS<EXT>, ES = ES<EXT>, GS = GS<EXT>>> Temporal
pub fn load_from_path(path: impl AsRef<Path>) -> Result<Self, StorageError> {
let path = path.as_ref();
let storage = Layer::load(path)?;
let id_type = storage.nodes().id_type();

let gid_resolver_dir = path.join("gid_resolver");
let resolver = GIDResolver::new_with_path(&gid_resolver_dir)?;
let resolver = GIDResolver::new_with_path(&gid_resolver_dir, id_type)?;
let node_count = AtomicUsize::new(storage.nodes().num_nodes());
let wal_dir = path.join("wal");
let wal = Arc::new(WalImpl::new(Some(wal_dir))?);
Expand Down Expand Up @@ -184,9 +185,15 @@ impl<EXT: PersistentStrategy<NS = NS<EXT>, ES = ES<EXT>, GS = GS<EXT>>> Temporal
std::fs::create_dir_all(dir)?
}

let id_type = node_meta
.metadata_mapper()
.d_types()
.first()
.and_then(|dtype| GidType::from_prop_type(dtype));

let gid_resolver_dir = graph_dir.as_ref().map(|dir| dir.gid_resolver_dir());
let logical_to_physical = match gid_resolver_dir {
Some(gid_resolver_dir) => GIDResolver::new_with_path(gid_resolver_dir)?,
Some(gid_resolver_dir) => GIDResolver::new_with_path(gid_resolver_dir, id_type)?,
None => GIDResolver::new()?,
}
.into();
Expand All @@ -212,8 +219,9 @@ impl<EXT: PersistentStrategy<NS = NS<EXT>, ES = ES<EXT>, GS = GS<EXT>>> Temporal
})
}

pub fn disk_storage_enabled(&self) -> bool {
self.graph_dir().is_some() && Extension::disk_storage_enabled()
pub fn disk_storage_path(&self) -> Option<&Path> {
self.graph_dir()
.filter(|_| Extension::disk_storage_enabled())
}

pub fn extension(&self) -> &EXT {
Expand Down
6 changes: 1 addition & 5 deletions db4-storage/src/pages/edge_page/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@ use crate::{
LocalPOS, api::edges::EdgeSegmentOps, error::StorageError, pages::layer_counter::GraphStats,
segments::edge::segment::MemEdgeSegment,
};
use arrow_array::{ArrayRef, BooleanArray};
use raphtory_api::core::entities::{VID, properties::prop::Prop};
use raphtory_core::{
entities::EID,
storage::timeindex::{AsTime, TimeIndexEntry},
};
use raphtory_core::storage::timeindex::{AsTime, TimeIndexEntry};
use std::ops::DerefMut;

pub struct EdgeWriter<
Expand Down
2 changes: 0 additions & 2 deletions db4-storage/src/pages/layer_counter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ impl GraphStats {
}
} else {
// we need to create the layer
self.layers.reserve(layer_id + 1 - self.layers.count());

loop {
let new_layer_id = self.layers.push_with(|_| Default::default());
if new_layer_id >= layer_id {
Expand Down
24 changes: 8 additions & 16 deletions db4-storage/src/pages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@ fn write_graph_config<EXT: Config>(
config: &EXT,
) -> Result<(), StorageError> {
let config_file = graph_dir.as_ref().join("graph_config.json");
let config_file = std::fs::File::create(config_file).unwrap();
let config_file = std::fs::File::create(&config_file)?;

serde_json::to_writer_pretty(config_file, config)?;
Ok(())
}
Expand All @@ -459,7 +460,7 @@ fn read_graph_config<EXT: PersistentStrategy>(
graph_dir: impl AsRef<Path>,
) -> Result<EXT, StorageError> {
let config_file = graph_dir.as_ref().join("graph_config.json");
let config_file = std::fs::File::open(config_file).unwrap();
let config_file = std::fs::File::open(config_file)?;
let config = serde_json::from_reader(config_file)?;
Ok(config)
}
Expand All @@ -484,7 +485,7 @@ mod test {
make_nodes,
},
};
use chrono::{DateTime, NaiveDateTime, Utc};
use chrono::DateTime;
use proptest::prelude::*;
use raphtory_api::core::entities::properties::prop::Prop;
use raphtory_core::{entities::VID, storage::timeindex::TimeIndexOps};
Expand All @@ -498,10 +499,7 @@ mod test {
.collect();

check_edges_support(edges, par_load, false, |graph_dir| {
Layer::new(
Some(graph_dir),
crate::Extension::new(chunk_size, chunk_size),
)
Layer::new(Some(graph_dir), Extension::new(chunk_size, chunk_size))
})
}

Expand All @@ -511,10 +509,7 @@ mod test {
par_load: bool,
) {
check_edges_support(edges, par_load, false, |graph_dir| {
Layer::new(
Some(graph_dir),
crate::Extension::new(chunk_size, chunk_size),
)
Layer::new(Some(graph_dir), Extension::new(chunk_size, chunk_size))
})
}

Expand Down Expand Up @@ -766,14 +761,11 @@ mod test {
("857".to_owned(), Prop::F64(2.56)),
(
"296".to_owned(),
Prop::NDTime(NaiveDateTime::from_timestamp(1334043671, 0)),
Prop::NDTime(DateTime::from_timestamp(1334043671, 0).unwrap().naive_utc()),
),
(
"92".to_owned(),
Prop::DTime(DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp(994032315, 0),
Utc,
)),
Prop::DTime(DateTime::from_timestamp(994032315, 0).unwrap()),
),
],
)],
Expand Down
14 changes: 12 additions & 2 deletions db4-storage/src/pages/node_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use crate::{
segments::node::segment::MemNodeSegment,
};
use parking_lot::RwLockWriteGuard;
use raphtory_api::core::entities::properties::meta::Meta;
use raphtory_api::core::entities::{
GidType,
properties::{meta::Meta, prop::PropType},
};
use raphtory_core::{
entities::{EID, VID},
storage::timeindex::AsTime,
Expand All @@ -22,7 +25,6 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};

// graph // (nodes|edges) // graph segments // layers // chunks

#[derive(Debug)]
Expand Down Expand Up @@ -226,6 +228,14 @@ impl<NS: NodeSegmentOps<Extension = EXT>, EXT: Config> NodeStorageInner<NS, EXT>
Some(NodeWriter::new(segment, &self.stats, head))
}

pub fn id_type(&self) -> Option<GidType> {
self.node_meta
.metadata_mapper()
.d_types()
.first()
.and_then(|dtype| GidType::from_prop_type(dtype))
}

pub fn load(
nodes_path: impl AsRef<Path>,
edge_meta: Arc<Meta>,
Expand Down
8 changes: 4 additions & 4 deletions db4-storage/src/properties/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use bigdecimal::ToPrimitive;
use raphtory_api::core::entities::properties::{
meta::PropMapper,
prop::{
Prop, PropType, SerdeList, SerdeMap, arrow_dtype_from_prop_type, list_array_from_props,
struct_array_from_props,
Prop, PropType, SerdeArrowList, SerdeArrowMap, arrow_dtype_from_prop_type,
list_array_from_props, struct_array_from_props,
},
};
use raphtory_core::{
Expand Down Expand Up @@ -206,7 +206,7 @@ impl Properties {
.unwrap();
let array_iter = indices
.map(|i| lazy_vec.get_opt(i))
.map(|e| e.map(|m| SerdeMap(m)));
.map(|e| e.map(|m| SerdeArrowMap(m)));

let struct_array = struct_array_from_props(&dt, array_iter);

Expand All @@ -221,7 +221,7 @@ impl Properties {

let array_iter = indices
.map(|i| lazy_vec.get_opt(i))
.map(|opt_list| opt_list.map(SerdeList));
.map(|opt_list| opt_list.map(SerdeArrowList));

let list_array = list_array_from_props(&dt, array_iter);

Expand Down
16 changes: 14 additions & 2 deletions db4-storage/src/resolver/mapping_resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,20 @@ impl GIDResolverOps for MappingResolver {
})
}

fn new_with_path(_path: impl AsRef<Path>) -> Result<Self, StorageError> {
Self::new()
fn new_with_path(
_path: impl AsRef<Path>,
dtype: Option<GidType>,
) -> Result<Self, StorageError> {
match dtype {
None => Self::new(),
Some(dtype) => {
let mapping = match dtype {
GidType::U64 => Mapping::new_u64(),
GidType::Str => Mapping::new_str(),
};
Ok(Self { mapping })
}
}
}

fn len(&self) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion db4-storage/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub trait GIDResolverOps {
fn new() -> Result<Self, StorageError>
where
Self: Sized;
fn new_with_path(path: impl AsRef<Path>) -> Result<Self, StorageError>
fn new_with_path(path: impl AsRef<Path>, dtype: Option<GidType>) -> Result<Self, StorageError>
where
Self: Sized;
fn len(&self) -> usize;
Expand Down
1 change: 0 additions & 1 deletion db4-storage/src/segments/graph_prop/segment.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{
LocalPOS,
error::StorageError,
segments::{HasRow, SegmentContainer},
};
Expand Down
16 changes: 7 additions & 9 deletions db4-storage/src/segments/node/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,21 +550,19 @@ impl<P: PersistentStrategy<NS = NodeSegmentView<P>>> NodeSegmentOps for NodeSegm

#[cfg(test)]
mod test {
use std::sync::Arc;

use raphtory_api::core::entities::properties::{
meta::Meta,
prop::{Prop, PropType},
};
use raphtory_core::entities::{EID, ELID, VID};
use tempfile::tempdir;

use crate::{
LocalPOS, NodeSegmentView,
api::nodes::NodeSegmentOps,
pages::{layer_counter::GraphStats, node_page::writer::NodeWriter},
persist::strategy::NoOpStrategy,
};
use raphtory_api::core::entities::properties::{
meta::Meta,
prop::{Prop, PropType},
};
use raphtory_core::entities::{EID, ELID, VID};
use std::sync::Arc;
use tempfile::tempdir;

#[test]
fn est_size_changes() {
Expand Down
Loading
Loading