diff options
-rw-r--r-- | rust/Cargo.lock | 3 | ||||
-rw-r--r-- | rust/Cargo.toml | 5 | ||||
-rw-r--r-- | rust/src/api_server.rs | 59 | ||||
-rw-r--r-- | rust/src/database_models.rs | 222 | ||||
-rw-r--r-- | rust/src/lib.rs | 6 |
5 files changed, 274 insertions, 21 deletions
diff --git a/rust/Cargo.lock b/rust/Cargo.lock index b9b52098..8ac2eb79 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -212,7 +212,7 @@ dependencies = [ "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "pq-sys 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -339,6 +339,7 @@ dependencies = [ "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-term 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "swagger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 9883a18b..e4963b67 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -8,11 +8,12 @@ members = ["fatcat-api"] [dependencies] fatcat-api = {version = "*", path = "fatcat-api"} -diesel = { version = "1.2", features = ["postgres", "extras"] } +diesel = { version = "1.2", features = ["postgres", "extras", "uuid"] } dotenv = "0.9.0" clap = "*" error-chain = "0.11" -r2d2 = "*" +r2d2 = "0.8" +uuid = "0.5" # API server chrono = { version = "0.4", features = ["serde"] } diff --git a/rust/src/api_server.rs b/rust/src/api_server.rs index d9273186..aa13023d 100644 --- a/rust/src/api_server.rs +++ b/rust/src/api_server.rs @@ -1,13 +1,16 @@ //! API endpoint handlers use ConnectionPool; -use database_schema::container_rev::table as container_rev; +use database_models::*; +use database_schema::{container_rev, container_ident, container_edit, + creator_rev, creator_ident, creator_edit, + file_rev, file_ident, file_edit, + release_rev, release_ident, release_edit, + work_rev, work_ident, work_edit, +}; +use uuid; use diesel::prelude::*; use futures::{self, Future}; -//use database_schema::creator_rev::table as creator_rev; -//use database_schema::file_rev::table as file_rev; -//use database_schema::release_rev::table as release_rev; -//use database_schema::work_rev::table as work_rev; use fatcat_api::models; use fatcat_api::models::*; use fatcat_api::{Api, ApiError, ContainerIdGetResponse, ContainerLookupGetResponse, @@ -26,20 +29,26 @@ pub struct Server { impl Api for Server { fn container_id_get( &self, - _id: String, + id: String, _context: &Context, ) -> Box<Future<Item = ContainerIdGetResponse, Error = ApiError> + Send> { let conn = self.db_pool.get().expect("db_pool error"); - let c: i64 = container_rev.count().first(&*conn).expect("DB Error"); - println!("container count: {}", c); + let id = uuid::Uuid::parse_str(&id).unwrap(); + let c: ContainerIdentRow = container_ident::table + .find(id) + .first(&conn) + .expect("error loading container"); + //let c: i64 = container_rev::table.count().first(&conn).expect("DB Error"); + println!("container count: {:?}", c); + let ce = ContainerEntity { issn: None, publisher: Some("Hello!".into()), parent: None, name: None, state: None, - ident: None, - revision: None, + ident: Some(c.id.to_string()), + revision: c.rev_id.map(|v| v as isize), redirect: None, editgroup: None, }; @@ -81,13 +90,29 @@ impl Api for Server { id: String, context: &Context, ) -> Box<Future<Item = CreatorIdGetResponse, Error = ApiError> + Send> { - let context = context.clone(); - println!( - "creator_id_get(\"{}\") - X-Span-ID: {:?}", - id, - context.x_span_id.unwrap_or(String::from("<none>")).clone() - ); - Box::new(futures::failed("Generic failure".into())) + let conn = self.db_pool.get().expect("db_pool error"); + /* + let first_thing: (Uuid, bool, Option<i64>, Option<Uuid>) = creator_ident::table + .first(&conn) + .unwrap(); + let entity_table = creator_ident::table.left_join(creator_rev::table); + let thing: (creator_ident::SqlType, creator_rev::SqlType) = creator_ident::table + .inner_join(creator_rev::table) + .first(&conn) + .expect("Error loading creator"); + */ + let ce = CreatorEntity { + orcid: None, + name: None, + state: None, + ident: None, + revision: None, + redirect: None, + editgroup: None, + }; + Box::new(futures::done(Ok( + CreatorIdGetResponse::FetchASingleCreatorById(ce), + ))) } fn creator_lookup_get( diff --git a/rust/src/database_models.rs b/rust/src/database_models.rs new file mode 100644 index 00000000..c0118dda --- /dev/null +++ b/rust/src/database_models.rs @@ -0,0 +1,222 @@ + +use uuid::Uuid; +//use diesel::prelude::*; + +use database_schema::*; + +// Ugh. I thought the whole point was to *not* do this, but: +// https://github.com/diesel-rs/diesel/issues/1589 + +/* +table! { + changelog (id) { + id -> Int8, + editgroup_id -> Int8, + timestamp -> Nullable<Timestamp>, + } +} +*/ + +#[derive(Debug, Queryable, Identifiable, Associations)] // AsChangeset +#[table_name = "container_edit"] +pub struct ContainerEditRow { + pub id: i64, + pub ident_id: Uuid, + pub rev_id: Option<i64>, + pub redirect_id: Option<Uuid>, + pub editgroup_id: i64, + //pub extra_json: Option<Json>, +} + +#[derive(Debug, Queryable, Identifiable, Associations)] // AsChangeset +#[table_name = "container_ident"] +pub struct ContainerIdentRow { + pub id: Uuid, + pub is_live: bool, + pub rev_id: Option<i64>, + pub redirect_id: Option<Uuid>, +} + +#[derive(Debug, Queryable, Identifiable, Associations)] // AsChangeset +#[table_name = "container_rev"] +pub struct ContainerRevRow { + pub id: i64, + //extra_json: Option<Json>, + pub name: Option<String>, + pub parent_ident_id: Option<i64>, + pub publisher: Option<String>, + pub issn: Option<String>, +} + +/* +table! { + creator_edit (id) { + id -> Int8, + extra_json -> Nullable<Json>, + ident_id -> Uuid, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + editgroup_id -> Int8, + } +} + +table! { + creator_ident (id) { + id -> Uuid, + is_live -> Bool, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + } +} + +table! { + creator_rev (id) { + id -> Int8, + extra_json -> Nullable<Json>, + name -> Nullable<Text>, + orcid -> Nullable<Text>, + } +} + +table! { + editgroup (id) { + id -> Int8, + extra_json -> Nullable<Json>, + editor_id -> Int8, + description -> Nullable<Text>, + } +} + +table! { + editor (id) { + id -> Int8, + username -> Text, + is_admin -> Bool, + active_editgroup_id -> Nullable<Int8>, + } +} + +table! { + file_edit (id) { + id -> Int8, + extra_json -> Nullable<Json>, + ident_id -> Uuid, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + editgroup_id -> Int8, + } +} + +table! { + file_ident (id) { + id -> Uuid, + is_live -> Bool, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + } +} + +table! { + file_release (id) { + id -> Int8, + file_rev -> Int8, + target_release_ident_id -> Uuid, + } +} + +table! { + file_rev (id) { + id -> Int8, + extra_json -> Nullable<Json>, + size -> Nullable<Int4>, + sha1 -> Nullable<Text>, + url -> Nullable<Text>, + } +} + +table! { + release_contrib (id) { + id -> Int8, + release_rev -> Int8, + creator_ident_id -> Nullable<Uuid>, + stub -> Nullable<Text>, + contrib_type -> Nullable<Text>, + } +} + +table! { + release_edit (id) { + id -> Int8, + extra_json -> Nullable<Json>, + ident_id -> Uuid, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + editgroup_id -> Int8, + } +} + +table! { + release_ident (id) { + id -> Uuid, + is_live -> Bool, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + } +} + +table! { + release_ref (id) { + id -> Int8, + release_rev -> Int8, + target_release_ident_id -> Nullable<Uuid>, + index -> Nullable<Int4>, + stub -> Nullable<Text>, + } +} + +table! { + release_rev (id) { + id -> Int8, + extra_json -> Nullable<Json>, + work_ident_id -> Nullable<Uuid>, + container_ident_id -> Nullable<Uuid>, + title -> Nullable<Text>, + license -> Nullable<Text>, + release_type -> Nullable<Text>, + date -> Nullable<Text>, + doi -> Nullable<Text>, + volume -> Nullable<Text>, + pages -> Nullable<Text>, + issue -> Nullable<Text>, + } +} + +table! { + work_edit (id) { + id -> Int8, + extra_json -> Nullable<Json>, + ident_id -> Uuid, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + editgroup_id -> Int8, + } +} + +table! { + work_ident (id) { + id -> Uuid, + is_live -> Bool, + rev_id -> Nullable<Int8>, + redirect_id -> Nullable<Uuid>, + } +} + +table! { + work_rev (id) { + id -> Int8, + extra_json -> Nullable<Json>, + work_type -> Nullable<Text>, + primary_release_id -> Nullable<Uuid>, + } +} +*/ diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 56364be0..196dee36 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -3,6 +3,7 @@ extern crate fatcat_api; extern crate chrono; #[macro_use] extern crate diesel; +extern crate uuid; extern crate dotenv; extern crate futures; #[macro_use] @@ -15,6 +16,7 @@ extern crate r2d2; pub mod api_server; pub mod database_schema; +pub mod database_models; mod errors { error_chain!{} @@ -31,6 +33,8 @@ use std::env; pub type ConnectionPool = r2d2::Pool<ConnectionManager<diesel::pg::PgConnection>>; +/// Establish a direct database connection. Not currently used, but could be helpful for +/// single-threaded tests or utilities. pub fn establish_connection() -> PgConnection { dotenv().ok(); @@ -38,7 +42,7 @@ pub fn establish_connection() -> PgConnection { PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url)) } -/// Instantiate a new server. +/// Instantiate a new API server with a pooled database connection pub fn server() -> Result<api_server::Server> { dotenv().ok(); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); |