Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: express existing thread safety (as most things are immutable) #115

Merged
merged 8 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"
authors = ["Manuel Holtgrewe <[email protected]>"]
description = "Port of biocommons/hgvs to Rust"
license = "Apache-2.0"
homepage = "https://github.com/bihealth/seqrepo-rs"
homepage = "https://github.com/bihealth/hgvs-rs"
readme = "README.md"
rust-version = "1.64.0"

Expand All @@ -27,7 +27,7 @@ postgres = { version = "0.19", features = ["with-chrono-0_4"] }
quick_cache = "0.3"
regex = "1.7"
rustc-hash = "1.1"
seqrepo = { version = "0.5" }
seqrepo = { version = "0.6" }
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
Expand Down
45 changes: 26 additions & 19 deletions src/data/cdot/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
//!
//! https://github.com/SACGF/cdot

use std::{collections::HashMap, path::PathBuf, rc::Rc, time::Instant};
use std::{collections::HashMap, path::PathBuf, sync::Arc, time::Instant};

use crate::{
data::error::Error,
data::interface::{
GeneInfoRecord, Provider as ProviderInterface, TxExonsRecord, TxForRegionRecord,
TxIdentityInfo, TxInfoRecord, TxMappingOptionsRecord, TxSimilarityRecord,
self, GeneInfoRecord, TxExonsRecord, TxForRegionRecord, TxIdentityInfo, TxInfoRecord,
TxMappingOptionsRecord, TxSimilarityRecord,
},
static_data::{Assembly, ASSEMBLY_INFOS},
};

use bio::data_structures::interval_tree::ArrayBackedIntervalTree;
use chrono::NaiveDateTime;
use indexmap::IndexMap;
use seqrepo::{Interface as SeqRepoInterface, SeqRepo};
use seqrepo::{self, SeqRepo};

/// Configurationf or the `data::cdot::Provider`.
#[derive(Debug, PartialEq, Clone)]
Expand All @@ -42,7 +42,7 @@ pub struct Config {
/// `exon_aln_id`.
pub struct Provider {
inner: TxProvider,
seqrepo: Rc<dyn SeqRepoInterface>,
seqrepo: Arc<dyn seqrepo::Interface + Sync + Send>,
}

impl Provider {
Expand Down Expand Up @@ -70,14 +70,14 @@ impl Provider {
.collect::<Vec<&str>>()
.as_ref(),
)?,
seqrepo: Rc::new(SeqRepo::new(path, &instance)?),
seqrepo: Arc::new(SeqRepo::new(path, &instance)?),
})
}

/// Create a new provider allowing to inject a seqrepo.
pub fn with_seqrepo(
config: Config,
seqrepo: Rc<dyn SeqRepoInterface>,
seqrepo: Arc<dyn seqrepo::Interface + Sync + Send>,
) -> Result<Provider, Error> {
Ok(Self {
inner: TxProvider::with_config(
Expand All @@ -93,7 +93,7 @@ impl Provider {
}
}

impl ProviderInterface for Provider {
impl interface::Provider for Provider {
fn data_version(&self) -> &str {
self.inner.data_version()
}
Expand Down Expand Up @@ -699,7 +699,7 @@ pub static REQUIRED_VERSION: &str = "1.1";
/// The alignment method returned for all cdot transcripts.
pub static NCBI_ALN_METHOD: &str = "splign";

/// Implementation for `ProviderInterface`.
/// Implementation for `interface::Provider`.
impl TxProvider {
fn data_version(&self) -> &str {
REQUIRED_VERSION
Expand Down Expand Up @@ -1024,12 +1024,12 @@ impl TxProvider {
#[cfg(test)]
pub mod test_helpers {
use anyhow::Error;
use std::rc::Rc;
use std::sync::Arc;

use crate::data::uta_sr::test_helpers::build_writing_sr;

use super::{Config, Provider};
use seqrepo::{CacheReadingSeqRepo, Interface as SeqRepoInterface};
use seqrepo;

pub fn build_provider() -> Result<Provider, Error> {
let sr_cache_mode = std::env::var("TEST_SEQREPO_CACHE_MODE")
Expand All @@ -1040,8 +1040,8 @@ pub mod test_helpers {
log::debug!("building provider...");
let seqrepo = if sr_cache_mode == "read" {
log::debug!("reading provider...");
let seqrepo: Rc<dyn SeqRepoInterface> =
Rc::new(CacheReadingSeqRepo::new(sr_cache_path)?);
let seqrepo: Arc<dyn seqrepo::Interface + Send + Sync> =
Arc::new(seqrepo::CacheReadingSeqRepo::new(sr_cache_path)?);
log::debug!("construction done...");
seqrepo
} else if sr_cache_mode == "write" {
Expand All @@ -1066,8 +1066,9 @@ pub mod test_helpers {
#[cfg(test)]
pub mod tests {
use anyhow::Error;
use std::rc::Rc;

use std::str::FromStr;
use std::sync::Arc;

use chrono::NaiveDateTime;
use pretty_assertions::assert_eq;
Expand All @@ -1076,13 +1077,19 @@ pub mod tests {
use super::models::{gap_to_cigar, Container};
use super::test_helpers::build_provider;
use crate::data::interface::{
GeneInfoRecord, Provider as ProviderInterface, TxExonsRecord, TxForRegionRecord,
TxInfoRecord, TxMappingOptionsRecord, TxSimilarityRecord,
GeneInfoRecord, Provider, TxExonsRecord, TxForRegionRecord, TxInfoRecord,
TxMappingOptionsRecord, TxSimilarityRecord,
};
use crate::mapper::assembly::{Config as AssemblyMapperConfig, Mapper};
use crate::mapper::assembly::{self, Mapper};
use crate::parser::HgvsVariant;
use crate::static_data::Assembly;

#[test]
fn test_sync() {
fn is_sync<T: Sync>() {}
is_sync::<super::Provider>();
}

#[test]
fn deserialize_brca1() -> Result<(), Error> {
let json = std::fs::read_to_string(
Expand Down Expand Up @@ -2152,8 +2159,8 @@ pub mod tests {
}

fn build_mapper_37(normalize: bool) -> Result<Mapper, Error> {
let provider = Rc::new(build_provider()?);
let config = AssemblyMapperConfig {
let provider = Arc::new(build_provider()?);
let config = assembly::Config {
assembly: Assembly::Grch37,
normalize,
..Default::default()
Expand Down
16 changes: 11 additions & 5 deletions src/data/uta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::sequences::seq_md5;
use crate::static_data::{Assembly, ASSEMBLY_INFOS};

use crate::data::{
error::Error, interface::GeneInfoRecord, interface::Provider as ProviderInterface,
interface::TxExonsRecord, interface::TxForRegionRecord, interface::TxIdentityInfo,
interface::TxInfoRecord, interface::TxMappingOptionsRecord, interface::TxSimilarityRecord,
error::Error, interface, interface::GeneInfoRecord, interface::TxExonsRecord,
interface::TxForRegionRecord, interface::TxIdentityInfo, interface::TxInfoRecord,
interface::TxMappingOptionsRecord, interface::TxSimilarityRecord,
};

/// Configuration for the `data::uta::Provider`.
Expand Down Expand Up @@ -234,7 +234,7 @@ impl Provider {
}
}

impl ProviderInterface for Provider {
impl interface::Provider for Provider {
fn data_version(&self) -> &str {
&self.config.db_schema
}
Expand Down Expand Up @@ -604,11 +604,17 @@ impl ProviderInterface for Provider {

#[cfg(test)]
mod test {
use crate::{data::interface::Provider as ProviderInterface, static_data::Assembly};
use crate::{data::interface::Provider as InterfaceProvider, static_data::Assembly};
use anyhow::Error;

use super::{Config, Provider};

#[test]
fn test_sync() {
fn is_sync<T: Sync>() {}
is_sync::<super::Provider>();
}

fn get_config() -> Config {
Config {
db_url: std::env::var("TEST_UTA_DATABASE_URL")
Expand Down
58 changes: 31 additions & 27 deletions src/data/uta_sr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
//! * https://github.com/bihealth/seqrepo-rs

use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;

use crate::data::uta::{Config as UtaConfig, Provider as UtaProvider};
use crate::data::uta;
use crate::data::{
error::Error, interface::GeneInfoRecord, interface::Provider as ProviderInterface,
interface::TxExonsRecord, interface::TxForRegionRecord, interface::TxIdentityInfo,
interface::TxInfoRecord, interface::TxMappingOptionsRecord, interface::TxSimilarityRecord,
error::Error, interface, interface::GeneInfoRecord, interface::TxExonsRecord,
interface::TxForRegionRecord, interface::TxIdentityInfo, interface::TxInfoRecord,
interface::TxMappingOptionsRecord, interface::TxSimilarityRecord,
};
use seqrepo::{AliasOrSeqId, Interface as SeqRepoInterface, SeqRepo};
use seqrepo::{self, AliasOrSeqId, SeqRepo};

/// Configuration for the `data::uta_sr::Provider`.
#[derive(Debug, PartialEq, Clone)]
Expand All @@ -33,8 +33,8 @@ pub struct Config {
/// Transcripts from a UTA Postgres database, sequences comes from a SeqRepo. This makes
/// genome contig information available in contrast to `data::uta::Provider`.
pub struct Provider {
inner: UtaProvider,
seqrepo: Rc<dyn SeqRepoInterface>,
inner: uta::Provider,
seqrepo: Arc<dyn seqrepo::Interface + Send + Sync>,
}

impl Provider {
Expand All @@ -58,21 +58,21 @@ impl Provider {
.to_string();

Ok(Self {
inner: UtaProvider::with_config(&UtaConfig {
inner: uta::Provider::with_config(&uta::Config {
db_url: config.db_url.clone(),
db_schema: config.db_schema,
})?,
seqrepo: Rc::new(SeqRepo::new(path, &instance)?),
seqrepo: Arc::new(SeqRepo::new(path, &instance)?),
})
}

/// Create a new provider allowing to inject a seqrepo.
pub fn with_seqrepo(
config: Config,
seqrepo: Rc<dyn SeqRepoInterface>,
seqrepo: Arc<dyn seqrepo::Interface + Send + Sync>,
) -> Result<Provider, Error> {
Ok(Self {
inner: UtaProvider::with_config(&UtaConfig {
inner: uta::Provider::with_config(&uta::Config {
db_url: config.db_url.clone(),
db_schema: config.db_schema,
})?,
Expand All @@ -81,7 +81,7 @@ impl Provider {
}
}

impl ProviderInterface for Provider {
impl interface::Provider for Provider {
fn data_version(&self) -> &str {
self.inner.data_version()
}
Expand Down Expand Up @@ -174,18 +174,23 @@ impl ProviderInterface for Provider {
#[cfg(test)]
pub mod test_helpers {
use anyhow::Error;
use std::{path::PathBuf, rc::Rc};
use seqrepo::{CacheReadingSeqRepo, CacheWritingSeqRepo, SeqRepo};
use std::{path::PathBuf, sync::Arc};

use seqrepo::{
CacheReadingSeqRepo, CacheWritingSeqRepo, Interface as SeqRepoInterface, SeqRepo,
};
use crate::data::interface;

use super::{Config, Provider, ProviderInterface};
use super::{Config, Provider};

#[test]
fn test_sync() {
fn is_sync<T: Sync>() {}
is_sync::<super::Provider>();
}

/// Setup a UTA Provider with data source depending on environment variables.
///
/// See README.md for information on environment variable setup.
pub fn build_provider() -> Result<Rc<dyn ProviderInterface>, Error> {
pub fn build_provider() -> Result<Arc<dyn interface::Provider + Send + Sync>, Error> {
log::debug!("building provider...");
let db_url = std::env::var("TEST_UTA_DATABASE_URL")
.expect("Environment variable TEST_UTA_DATABASE_URL undefined!");
Expand All @@ -198,8 +203,8 @@ pub mod test_helpers {

let (seqrepo, seqrepo_path) = if sr_cache_mode == "read" {
log::debug!("reading provider...");
let seqrepo: Rc<dyn SeqRepoInterface> =
Rc::new(CacheReadingSeqRepo::new(sr_cache_path)?);
let seqrepo: Arc<dyn seqrepo::Interface + Send + Sync> =
Arc::new(CacheReadingSeqRepo::new(sr_cache_path)?);
log::debug!("construction done...");
(seqrepo, "".to_string())
} else if sr_cache_mode == "write" {
Expand All @@ -210,7 +215,7 @@ pub mod test_helpers {
};
log::debug!("now returning provider...");

Ok(Rc::new(Provider::with_seqrepo(
Ok(Arc::new(Provider::with_seqrepo(
Config {
db_url,
db_schema,
Expand All @@ -223,7 +228,7 @@ pub mod test_helpers {
/// Helper that builds the cache writing SeqRepo with inner stock SeqRepo.
pub fn build_writing_sr(
sr_cache_path: String,
) -> Result<(Rc<dyn SeqRepoInterface>, String), Error> {
) -> Result<(Arc<dyn seqrepo::Interface + Send + Sync>, String), Error> {
let seqrepo_path = std::env::var("TEST_SEQREPO_PATH")
.expect("Environment variable TEST_SEQREPO_PATH undefined!");
let path_buf = PathBuf::from(seqrepo_path.clone());
Expand All @@ -245,10 +250,9 @@ pub mod test_helpers {
.to_str()
.expect("problem with path to string conversion")
.to_string();
let seqrepo: Rc<dyn SeqRepoInterface> = Rc::new(CacheWritingSeqRepo::new(
SeqRepo::new(path, &instance)?,
sr_cache_path,
)?);
let seqrepo: Arc<dyn seqrepo::Interface + Send + Sync> = Arc::new(
CacheWritingSeqRepo::new(SeqRepo::new(path, &instance)?, sr_cache_path)?,
);
Ok((seqrepo, seqrepo_path))
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/mapper/alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
// n. -2 -1 ! 1 2 3 4 5 6 7 8 9
// g. ... 123 124 125 126 127 128 129 130 131 132 133 ...

use std::rc::Rc;
use std::sync::Arc;

use crate::{
data::interface::{Provider, TxExonsRecord},
Expand Down Expand Up @@ -119,7 +119,7 @@ pub struct Mapper {
/// Configuration for alignment mapping.
pub config: Config,
/// Data provider to use for the mapping.
pub provider: Rc<dyn Provider>,
pub provider: Arc<dyn Provider + Sync + Send>,

/// The transcript accession.
pub tx_ac: String,
Expand All @@ -138,7 +138,7 @@ pub struct Mapper {
impl Mapper {
pub fn new(
config: &Config,
provider: Rc<dyn Provider>,
provider: Arc<dyn Provider + Send + Sync>,
tx_ac: &str,
alt_ac: &str,
alt_aln_method: &str,
Expand Down Expand Up @@ -499,6 +499,12 @@ mod test {

use super::{build_tx_cigar, none_if_default, Mapper};

#[test]
fn test_sync() {
fn is_sync<T: Sync>() {}
is_sync::<super::Mapper>();
}

#[test]
fn build_tx_cigar_empty() {
assert!(build_tx_cigar(&Vec::new(), 1).is_err());
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/altseq.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Code for building alternative sequence and convertion to HGVS.p.

use std::{cmp::Ordering, rc::Rc};
use std::{cmp::Ordering, sync::Arc};

use crate::{
data::interface::Provider,
Expand Down Expand Up @@ -35,7 +35,7 @@ impl RefTranscriptData {
/// * `tx_ac` -- Transcript accession.
/// * `pro_ac` -- Protein accession.
pub fn new(
provider: Rc<dyn Provider>,
provider: Arc<dyn Provider + Send + Sync>,
tx_ac: &str,
pro_ac: Option<&str>,
) -> Result<Self, Error> {
Expand Down
Loading