Skip to content

Commit

Permalink
feat: express existing thread safety (as most things are immutable) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
holtgrewe authored Jun 12, 2023
1 parent 94706de commit 0d6f241
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 105 deletions.
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 <manuel.holtgrewe@bih-charite.de>"]
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

0 comments on commit 0d6f241

Please sign in to comment.