Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
09d82c0
`update_links` + base for smart filter
uselessgoddess Jun 24, 2022
6cbd788
Update + Delete + Some fixes
uselessgoddess Jun 25, 2022
49376d1
Use old standard
uselessgoddess Jun 25, 2022
6fa2b31
Remove extra collect and into_iter
FreePhoenix888 Jun 28, 2022
b0218f2
Migrate to new doublets
uselessgoddess Jun 29, 2022
7e073bf
Merge remote-tracking branch 'origin/main_mirror' into main_mirror
uselessgoddess Jun 29, 2022
95ae7e0
Fix borrowing error
uselessgoddess Jun 29, 2022
63c1744
Use self.0.iter() in iter()
FreePhoenix888 Jun 29, 2022
de96381
Merge branch 'main_mirror' of github.com:linksplatform/Data.Doublets.…
FreePhoenix888 Jun 29, 2022
d33e848
Implement distinct_on, limit, offset
FreePhoenix888 Jun 29, 2022
b431732
Dereference box
FreePhoenix888 Jun 29, 2022
536a19d
Implement `distinct_on` algorithm
uselessgoddess Jun 29, 2022
588ab92
First steps in ordering
uselessgoddess Jul 5, 2022
dd9c55a
Remove useless feature
uselessgoddess Jul 5, 2022
ecff7e9
Fix copilot typo
uselessgoddess Jul 5, 2022
121dc9b
Use unsafe magic
uselessgoddess Jul 5, 2022
3bedae9
Fix `LinkType` mismatching
uselessgoddess Jul 5, 2022
ff0e0ec
Fix limit/offset mismatching
uselessgoddess Jul 5, 2022
82e616a
Remove unsafe magic
uselessgoddess Jul 6, 2022
d8dbf92
Necessary `.into_par_iter`
uselessgoddess Jul 11, 2022
73ba856
Update server to modern doublets api
uselessgoddess Jul 14, 2022
5fb007c
Use `doublets` from git latest
uselessgoddess Aug 6, 2022
5fa44d8
Add `mimalloc` as global allocator feature
uselessgoddess Aug 6, 2022
cd5f5c0
Add `jemalloc` feature for `linux-x86_64`
uselessgoddess Aug 7, 2022
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
25 changes: 18 additions & 7 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@ version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1.19", features = ["full"] }
async-std = { version = "1.12", features = ["attributes"] }
async-graphql = "4.0"
actix-web = "4.0"
async-graphql-actix-web = "4.0"
#doublets = { version = "0.1.0-alpha.20", features = ["full"] }
doublets = "0.1.0-beta.3"
actix-web = { version = "4.1.0" }
async-graphql = { version = "4.0.6" }
async-graphql-actix-web = { version = "4.0.6" }
itertools = { version = "0.10.3" }
smallvec = { version = "1.9.0" }
rayon = { version = "1.5.3" }

tokio = { version = "1.19", features = ["macros", "rt-multi-thread"] }

doublets = { git = "https://github.com/linksplatform/doublets-rs" }

mimalloc = { version = "0.1", default-features = false, optional = true }

[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies]
jemalloc = { package = "tikv-jemallocator", version = "0.5.0", optional = true }

[features]
default = ["mimalloc"]
35 changes: 20 additions & 15 deletions rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#![feature(never_type)]
#![feature(result_flattening)]
#![feature(box_syntax)]
#![feature(try_trait_v2)]

mod model;
mod store;

use crate::model::{
Links, LinksInsertInput, LinksMutationResponse, LinksOnConflict, LinksOptionExt, MutationRoot,
QueryRoot,
LinkType, Links, LinksInsertInput, LinksMutationResponse, LinksOnConflict, LinksOptionExt,
MutationRoot, QueryRoot,
};
use actix_web::{guard, web, App, HttpResponse, HttpServer, Responder};
use async_graphql::{
Expand All @@ -14,12 +17,11 @@ use async_graphql::{
};
use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};
use async_std::sync::RwLock;
use doublets::mem::FileMappedMem;
use doublets::{splited, Link};
use doublets::mem::FileMapped;
use doublets::{split, Doublets, Link};
use std::{error::Error, fs::File, io, path::Path};

// todo: wait for fix type infer
type RawStore = splited::Store<u64, FileMappedMem, FileMappedMem>;
type RawStore = Box<dyn Doublets<LinkType>>;
type Store = RwLock<RawStore>;
type Schema = async_graphql::Schema<QueryRoot, MutationRoot, EmptySubscription>;

Expand All @@ -35,20 +37,16 @@ async fn index_playground() -> actix_web::Result<HttpResponse> {
}

// todo: may be add support async-std files to platform-mem
fn map_db_file<P: AsRef<Path>>(path: P) -> io::Result<FileMappedMem> {
File::options()
.create(true)
.read(true)
.write(true)
.open(path)
.map(FileMappedMem::new)
.flatten()
fn map_db_file<T: Default, P: AsRef<Path>>(path: P) -> io::Result<FileMapped<T>> {
FileMapped::from_path(path)
}

#[tokio::main]
// todo: implement Into<io::Error> for LinksError
async fn main() -> Result<(), Box<dyn Error>> {
let store = RawStore::new(map_db_file("db.links")?, map_db_file("index.links")?)?;
let store =
split::Store::<LinkType, _, _>::new(map_db_file("db.links")?, map_db_file("index.links")?)?;
let store: Box<dyn Doublets<_>> = box store::Store::new(store);
let schema = Schema::build(QueryRoot, MutationRoot, EmptySubscription)
.data(Store::new(store))
.finish();
Expand All @@ -66,3 +64,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
.await
.map_err(|e| e.into())
}

#[cfg(feature = "mimalloc")]
#[global_allocator]
static MIMALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;

#[cfg(feature = "jemalloc")]
static JEMALLOC: jemalloc::Jemalloc = jemalloc::Jemalloc;
32 changes: 32 additions & 0 deletions rust/src/model/distinct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use crate::model::LinkType;
use doublets::Link;
use std::hash::{Hash, Hasher};

pub struct DistinctWrapper {
matches: (LinkType, LinkType),
link: Link<LinkType>,
}

impl DistinctWrapper {
pub fn from_match_link(matches: (LinkType, LinkType), link: Link<LinkType>) -> Self {
Self { matches, link }
}

pub fn into_link(self) -> Link<LinkType> {
self.link
}
}

impl Hash for DistinctWrapper {
fn hash<H: Hasher>(&self, state: &mut H) {
self.matches.hash(state)
}
}

impl PartialEq<Self> for DistinctWrapper {
fn eq(&self, other: &Self) -> bool {
&self.matches == &other.matches
}
}

impl Eq for DistinctWrapper {}
2 changes: 1 addition & 1 deletion rust/src/model/enum_type/links_select_column.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use async_graphql::*;

#[derive(Enum, Debug, Copy, Clone, Eq, PartialEq)]
#[derive(Enum, Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[graphql(name = "links_select_column")]
pub enum LinksSelectColumn {
#[graphql(name = "from_id")]
Expand Down
15 changes: 15 additions & 0 deletions rust/src/model/enum_type/order_by.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::model::LinkType;
use async_graphql::*;
use std::cmp::Ordering;

#[derive(Enum, Debug, Copy, Clone, Eq, PartialEq)]
#[graphql(name = "order_by")]
Expand All @@ -16,3 +18,16 @@ pub enum OrderBy {
#[graphql(name = "desc_nulls_last")]
DescNullsLast,
}

impl OrderBy {
pub fn matches(&self, a: LinkType, b: LinkType) -> Ordering {
match self {
OrderBy::Asc => a.cmp(&b),
OrderBy::AscNullsFirst => a.cmp(&b),
OrderBy::AscNullsLast => a.cmp(&b),
OrderBy::Desc => b.cmp(&a),
OrderBy::DescNullsFirst => b.cmp(&a),
OrderBy::DescNullsLast => b.cmp(&a),
}
}
}
1 change: 0 additions & 1 deletion rust/src/model/input_object_type/bigint_comparison_exp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::model::{Bigint, LinkType};
use crate::RawStore;
use async_graphql::*;
use doublets::Doublets;

Expand Down
24 changes: 23 additions & 1 deletion rust/src/model/input_object_type/links_order_by.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::model::CanAggregateOrderBy;
use crate::model::LinksAggregateOrderBy;
use crate::model::MpAggregateOrderBy;
use crate::model::NumbersOrderBy;
use crate::model::ObjectsOrderBy;
use crate::model::OrderBy;
use crate::model::SelectorsAggregateOrderBy;
use crate::model::StringsOrderBy;
use crate::model::{CanAggregateOrderBy, LinkType};
use async_graphql::*;
use doublets::Link;
use std::cmp::Ordering;

#[derive(InputObject, Debug)]
#[graphql(name = "links_order_by")]
Expand Down Expand Up @@ -52,3 +54,23 @@ pub struct LinksOrderBy {
pub typed_aggregate: Option<LinksAggregateOrderBy>,
pub value: Option<OrderBy>,
}

impl LinksOrderBy {
pub fn matches(&self, a: &Link<LinkType>, b: &Link<LinkType>) -> Ordering {
let mut ord = Ordering::Equal;

if let Some(id) = self.id {
ord = ord.then_with(|| id.matches(a.index, b.index));
}

if let Some(from_id) = self.from_id {
ord = ord.then_with(|| from_id.matches(a.source, b.source));
}

if let Some(to_id) = self.to_id {
ord = ord.then_with(|| to_id.matches(a.target, b.target));
}

ord
}
}
9 changes: 6 additions & 3 deletions rust/src/model/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
mod distinct;
mod enum_type;
mod input_object_type;
mod iterator;
mod object_type;
mod scalar_type;

use doublets::data::LinksError;
use doublets::data::Error;
pub use enum_type::CanSelectColumn;
pub use enum_type::LinksConstraint;
pub use enum_type::LinksSelectColumn;
Expand Down Expand Up @@ -234,10 +235,12 @@ pub use scalar_type::Jsonb;
pub use scalar_type::LinksOptionExt;
use std::marker::PhantomData;

pub use distinct::DistinctWrapper;

pub type LinkType = u64;
pub type LinksResult<T> = Result<T, LinksError<u64>>;
pub type LinksResult<T> = Result<T, Error<LinkType>>;

struct LinkTypeAssert<T: doublets::num::LinkType>(PhantomData<T>);
struct LinkTypeAssert<T: doublets::data::LinkType>(PhantomData<T>);

#[allow(dead_code)]
#[allow(non_camel_case_types)]
Expand Down
5 changes: 3 additions & 2 deletions rust/src/model/object_type/links.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::model::Bigint;
use crate::model::Can;
use crate::model::CanAggregate;
use crate::model::CanBoolExp;
Expand All @@ -25,12 +24,14 @@ use crate::model::SelectorsOrderBy;
use crate::model::SelectorsSelectColumn;
use crate::model::Strings;
use crate::model::UpLinksArgs;
use crate::model::{Bigint, LinkType};
use crate::Store;
use async_graphql::*;
use doublets::Doublets;

#[derive(Debug, Clone)]
pub struct Links(pub doublets::Link<u64>);
#[repr(transparent)]
pub struct Links(pub doublets::Link<LinkType>);

#[Object(name = "links")]
impl Links {
Expand Down
67 changes: 60 additions & 7 deletions rust/src/model/object_type/mutation_root.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::model::Links;
use crate::model::LinksBoolExp;
use crate::model::LinksIncInput;
use crate::model::LinksInsertInput;
Expand Down Expand Up @@ -44,10 +43,12 @@ use crate::model::StringsOnConflict;
use crate::model::StringsPkColumnsInput;
use crate::model::StringsSetInput;
use crate::model::{Bigint, LinksResult};
use crate::Store;
use crate::model::{LinkType, Links};
use crate::{QueryRoot, Store};
use async_graphql::*;
use doublets::data::{LinksError, Query};
use doublets::data::{Error, Query};
use doublets::{Doublets, Link};
use smallvec::{smallvec, SmallVec};
use std::io::{Read, Write};

pub use crate::model::LinksOptionExt;
Expand All @@ -62,9 +63,27 @@ impl MutationRoot {
&self,
ctx: &Context<'_>,
_where: Box<LinksBoolExp>,
) -> Option<LinksMutationResponse> {
todo!()
) -> Result<Option<LinksMutationResponse>> {
let mut store = ctx.data_unchecked::<Store>().write().await;

let ids: Vec<_> = QueryRoot::filter_links(&*store, Some(_where))
.await
.map(|link| link.index)
.collect();

let returning: LinksResult<Vec<_>> = ids
.into_iter()
.map(move |id| -> LinksResult<_> {
let link = store.try_get_link(id)?;
store.delete(id)?;
Ok(Links(link))
})
.collect();
returning
.map(|s| Some(LinksMutationResponse(s)))
.map_err(|e| e.into())
}

#[graphql(name = "delete_links_by_pk")]
pub async fn delete_links_by_pk(&self, ctx: &Context<'_>, id: Bigint) -> Option<Links> {
todo!()
Expand Down Expand Up @@ -230,16 +249,50 @@ impl MutationRoot {
) -> Option<Strings> {
todo!()
}

#[graphql(name = "update_links")]
pub async fn update_links(
&self,
ctx: &Context<'_>,
#[graphql(name = "_inc")] inc: Option<LinksIncInput>,
#[graphql(name = "_set")] set: Option<LinksSetInput>,
_where: Box<LinksBoolExp>,
) -> Option<LinksMutationResponse> {
todo!()
) -> Result<Option<LinksMutationResponse>> {
let mut store = ctx.data_unchecked::<Store>().write().await;

let ids: Vec<_> = QueryRoot::filter_links(&*store, Some(_where))
.await
.map(|link| link.index)
.collect();

let returning: LinksResult<Vec<_>> = ids
.into_iter()
.map(move |id| -> LinksResult<_> {
let link = store.try_get_link(id)?;
let (from_id, to_id) = if let Some(inc) = &inc {
(
link.source + inc.from_id.to_link(),
link.target + inc.from_id.to_link(),
)
} else if let Some(set) = &set {
(set.from_id.to_link(), set.to_id.to_link())
} else {
(link.source, link.target)
};

if (link.source, link.target) != (from_id, to_id) {
let id = store.update(id, from_id, to_id)?;
Ok(Links(Link::new(id, from_id, to_id)))
} else {
Ok(Links(link))
}
})
.collect();
returning
.map(|s| Some(LinksMutationResponse(s)))
.map_err(|e| e.into())
}

#[graphql(name = "update_links_by_pk")]
pub async fn update_links_by_pk(
&self,
Expand Down
Loading