Skip to content

Commit

Permalink
feat(ConfigReader): take an Option<Arc<dyn FileIO>>
Browse files Browse the repository at this point in the history
  • Loading branch information
mogery committed Jan 31, 2024
1 parent ce9db97 commit c7a8411
Show file tree
Hide file tree
Showing 10 changed files with 26 additions and 36 deletions.
2 changes: 1 addition & 1 deletion src/cli/tc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub async fn run() -> Result<()> {
update_checker::check_for_update().await;
let file_io: Arc<dyn FileIO + Send + Sync> = init_file();

Check warning on line 28 in src/cli/tc.rs

View check run for this annotation

Codecov / codecov/patch

src/cli/tc.rs#L28

Added line #L28 was not covered by tests
let default_http_io = init_http(&Upstream::default(), None);
let config_reader = ConfigReader::init(file_io.clone(), default_http_io);
let config_reader = ConfigReader::init(Some(file_io.clone()), default_http_io);

Check warning on line 30 in src/cli/tc.rs

View check run for this annotation

Codecov / codecov/patch

src/cli/tc.rs#L30

Added line #L30 was not covered by tests
match cli.command {
Command::Start { file_paths } => {
let config_set = config_reader.read_all(&file_paths).await?;
Expand Down
23 changes: 12 additions & 11 deletions src/config/reader.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::{HashMap, VecDeque};
use std::sync::Arc;

use anyhow::Context;
use anyhow::{anyhow, Context};
use futures_util::future::join_all;
use futures_util::TryFutureExt;
use prost_reflect::prost_types::{FileDescriptorProto, FileDescriptorSet};
Expand All @@ -16,7 +16,7 @@ const NULL_STR: &str = "\0\0\0\0\0\0\0";

/// Reads the configuration from a file or from an HTTP URL and resolves all linked extensions to create a ConfigSet.
pub struct ConfigReader {
file_io: Arc<dyn FileIO + Send>,
file_io: Option<Arc<dyn FileIO + Send + Sync>>,
http_io: Arc<dyn HttpIO + Send + Sync>,
}

Expand All @@ -28,7 +28,7 @@ struct FileRead {

impl ConfigReader {
pub fn init(
file_io: Arc<dyn FileIO + Send + Sync>,
file_io: Option<Arc<dyn FileIO + Send + Sync>>,
http_io: Arc<dyn HttpIO + Send + Sync>,
) -> Self {
Self { file_io, http_io }
Expand All @@ -44,10 +44,11 @@ impl ConfigReader {
.await?;

String::from_utf8(response.body.to_vec())?
} else if let Some(file_io) = &self.file_io {
// Is a file path and file IO is enabled
file_io.read(&file.to_string()).await?
} else {
// Is a file path

self.file_io.read(&file.to_string()).await?
return Err(anyhow!("Cannot read file {:#?}", file.to_string()));
};

Ok(FileRead { content, path: file.to_string() })
Expand Down Expand Up @@ -196,7 +197,7 @@ mod test_proto_config {
#[tokio::test]
async fn test_resolve() {
// Skipping IO tests as they are covered in reader.rs
let reader = ConfigReader::init(init_file(), init_http(&Default::default(), None));
let reader = ConfigReader::init(Some(init_file()), init_http(&Default::default(), None));
reader
.read_proto("google/protobuf/empty.proto")
.await
Expand All @@ -222,7 +223,7 @@ mod test_proto_config {
assert!(test_file.exists());
let test_file = test_file.to_str().unwrap().to_string();

let reader = ConfigReader::init(init_file(), init_http(&Default::default(), None));
let reader = ConfigReader::init(Some(init_file()), init_http(&Default::default(), None));
let helper_map = reader
.resolve_descriptors(HashMap::new(), test_file)
.await?;
Expand Down Expand Up @@ -312,7 +313,7 @@ mod reader_tests {
.iter()
.map(|x| x.to_string())
.collect();
let cr = ConfigReader::init(file_io, http_io);
let cr = ConfigReader::init(Some(file_io), http_io);
let c = cr.read_all(&files).await.unwrap();
assert_eq!(
["Post", "Query", "Test", "User"]
Expand Down Expand Up @@ -341,7 +342,7 @@ mod reader_tests {
.iter()
.map(|x| x.to_string())
.collect();
let cr = ConfigReader::init(file_io, http_io);
let cr = ConfigReader::init(Some(file_io), http_io);
let c = cr.read_all(&files).await.unwrap();
assert_eq!(
["Post", "Query", "User"]
Expand All @@ -361,7 +362,7 @@ mod reader_tests {
let http_io = init_http(&Upstream::default(), None);

let cargo_manifest = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let reader = ConfigReader::init(file_io, http_io);
let reader = ConfigReader::init(Some(file_io), http_io);

let config = reader
.read(&format!(
Expand Down
2 changes: 1 addition & 1 deletion src/grpc/data_loader_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ mod tests {
"foo".to_string(),
Type::default().fields(vec![("bar", Field::default().grpc(grpc))]),
);
let reader = ConfigReader::init(file_io, http_io);
let reader = ConfigReader::init(Some(file_io), http_io);
let config_set = reader.resolve(config).await.unwrap();

let protobuf_set =
Expand Down
2 changes: 1 addition & 1 deletion src/grpc/protobuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ mod tests {
async fn get_proto_file(name: &str) -> Result<FileDescriptorSet> {
let file_io = init_file();
let http_io = init_http(&Upstream::default(), None);
let reader = ConfigReader::init(file_io, http_io);
let reader = ConfigReader::init(Some(file_io), http_io);
let mut config = Config::default();
let grpc = Grpc {
proto_path: get_test_file(name)
Expand Down
2 changes: 1 addition & 1 deletion src/grpc/request_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ mod tests {

let file_io = init_file();
let http_io = init_http(&Upstream::default(), None);
let reader = ConfigReader::init(file_io, http_io);
let reader = ConfigReader::init(Some(file_io), http_io);
let mut config = Config::default();
let grpc = Grpc {
proto_path: test_file.to_str().unwrap().to_string(),
Expand Down
17 changes: 3 additions & 14 deletions src/http/showcase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,12 @@ pub async fn showcase_get_app_ctx<T: DeserializeOwned + GraphQLRequestLike>(
return Ok(Err(GraphQLResponse::from(response).to_response()?));
};

let config = if let Some(file) = resources.file {
let reader = ConfigReader::init(file, http.clone());
reader.read(config_url).await
} else {
let reader = ConfigReader::init(Arc::new(DummyFileIO), http.clone());
reader.read(config_url).await
};

let config = match config {
let reader = ConfigReader::init(resources.file, http.clone());
let config = match reader.read(config_url).await {
Ok(config) => config,
Err(e) => {
let mut response = async_graphql::Response::default();
let server_error = if format!("{:?}", e.source()) == "Some(\"DummyFileIO\")" {
ServerError::new("Invalid Config URL specified", None)
} else {
ServerError::new(format!("{}", e), None)
};
let server_error = ServerError::new(format!("Failed to read config: {}", e), None);
response.errors = vec![server_error];
return Ok(Err(GraphQLResponse::from(response).to_response()?));
}
Expand Down
4 changes: 2 additions & 2 deletions tests/graphql_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ async fn test_server_to_client_sdl() -> std::io::Result<()> {
let content = content.as_str();
let config = Config::from_sdl(content).to_result().unwrap();
let upstream = config.upstream.clone();
let reader = ConfigReader::init(file_io.clone(), init_http(&upstream, None));
let reader = ConfigReader::init(Some(file_io.clone()), init_http(&upstream, None));
let config_set = reader.resolve(config).await.unwrap();
let actual =
print_schema::print_schema((Blueprint::try_from(&config_set).unwrap()).to_schema());
Expand Down Expand Up @@ -391,7 +391,7 @@ async fn test_failures_in_client_sdl() -> std::io::Result<()> {
let actual = match config {
Ok(config) => {
let upstream = config.upstream.clone();
let reader = ConfigReader::init(file_io.clone(), init_http(&upstream, None));
let reader = ConfigReader::init(Some(file_io.clone()), init_http(&upstream, None));
match reader.resolve(config).await {
Ok(config_set) => Valid::from(Blueprint::try_from(&config_set))
.to_result()
Expand Down
4 changes: 2 additions & 2 deletions tests/http/showcase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ assert:
body:
data: null
errors:
- message: "Invalid Config URL specified"
- message: "Failed to read config: ./tests/http/config/simple.graphql"
- request:
method: POST
url: http://localhost:8080/showcase/graphql?config=http%3A%2F%2Fexample.com%2Finvalid.graphql
Expand All @@ -69,7 +69,7 @@ assert:
body:
data: null
errors:
- message: "Validation Error\n• --> 1:1\n |\n1 | \"dsjfsjdfjdsfjkdskjfjkds\"\n | ^---\n |\n = expected type_system_definition\n"
- message: "Failed to read config: Validation Error\n• --> 1:1\n |\n1 | \"dsjfsjdfjdsfjkdskjfjkds\"\n | ^---\n |\n = expected type_system_definition\n"
- request:
method: POST
url: http://localhost:8080/showcase/graphql?config=http%3A%2F%2Fexample.com%2Fsimple.graphql
Expand Down
2 changes: 1 addition & 1 deletion tests/http_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl HttpSpec {
let http_client = init_http(&Upstream::default(), None);
let config = match self.config.clone() {
ConfigSource::File(file) => {
let reader = ConfigReader::init(file_io, http_client);
let reader = ConfigReader::init(Some(file_io), http_client);
reader.read_all(&[file]).await.unwrap()
}
ConfigSource::Inline(config) => ConfigSet::from(config),
Expand Down
4 changes: 2 additions & 2 deletions tests/server_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tailcall::config::Upstream;
async fn test_server(configs: &[&str], url: &str) {
let file_io = init_file();
let http_client = init_http(&Upstream::default(), None);
let reader = ConfigReader::init(file_io, http_client);
let reader = ConfigReader::init(Some(file_io), http_client);
let config = reader.read_all(configs).await.unwrap();
let mut server = Server::new(config);
let server_up_receiver = server.server_up_receiver();
Expand Down Expand Up @@ -94,7 +94,7 @@ async fn server_start_http2_nokey() {
let configs = &["tests/server/config/server-start-http2-nokey.graphql"];
let file_io = init_file();
let http_client = init_http(&Upstream::default(), None);
let reader = ConfigReader::init(file_io, http_client);
let reader = ConfigReader::init(Some(file_io), http_client);
let config = reader.read_all(configs).await.unwrap();
let server = Server::new(config);
assert!(server.start().await.is_err())
Expand Down

1 comment on commit c7a8411

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running 30s test @ http://localhost:8000/graphql

4 threads and 100 connections

Thread Stats Avg Stdev Max +/- Stdev
Latency 6.60ms 2.84ms 30.06ms 69.11%
Req/Sec 3.82k 253.26 5.81k 89.92%

456489 requests in 30.02s, 2.29GB read

Requests/sec: 15203.79

Transfer/sec: 78.04MB

Please sign in to comment.