Now all features are not activated by default.

This commit is contained in:
Sunli 2021-03-22 10:39:17 +08:00
parent 7fb02d587e
commit 1c32a8afcb
18 changed files with 57 additions and 90 deletions

View File

@ -25,8 +25,8 @@ jobs:
run: cargo fmt --all -- --check run: cargo fmt --all -- --check
- name: Check with clippy - name: Check with clippy
run: cargo clippy --all run: cargo clippy --all
- name: Build without features - name: Build with all features
run: cargo build --no-default-features run: cargo build --all-features
- name: Build - name: Build
run: cargo build --all --verbose run: cargo build --all --verbose
- name: Run tests - name: Run tests
@ -49,7 +49,7 @@ jobs:
toolchain: nightly toolchain: nightly
override: true override: true
components: clippy, rustfmt components: clippy, rustfmt
- name: Build on nightly without features - name: Build on nightly with all features
run: cargo build --no-default-features run: cargo build --all-features
- name: Build on nightly - name: Build on nightly
run: cargo build --all --verbose run: cargo build --all --verbose

View File

@ -4,9 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [2.6.3] - 2021-03-22
- Add `extension::OpenTelemetry` and delete `extension::Tracing`. ### Added
- Add `extension::OpenTelemetry`.
### - [Changed]
- Now all features are not activated by default.
- Remove `multipart` feature.
## [2.6.2] - 2021-03-20 ## [2.6.2] - 2021-03-20

View File

@ -13,30 +13,12 @@ categories = ["network-programming", "asynchronous"]
readme = "README.md" readme = "README.md"
[features] [features]
default = [ default = []
"apollo_persisted_queries",
"apollo_tracing",
"bson",
"chrono",
"chrono-tz",
"log",
"multipart",
"string_number",
"tracing",
"opentelemetry",
"unblock",
"url",
"uuid",
"dataloader"
]
apollo_tracing = ["chrono"] apollo_tracing = ["chrono"]
apollo_persisted_queries = ["lru", "sha2"] apollo_persisted_queries = ["lru", "sha2"]
multipart = ["multer", "tempfile"]
unblock = ["blocking"] unblock = ["blocking"]
string_number = ["num-traits"] string_number = ["num-traits"]
dataloader = ["futures-timer", "futures-channel"] dataloader = ["futures-timer", "futures-channel"]
# Used for doc(cfg())
nightly = []
[dependencies] [dependencies]
async-graphql-derive = { path = "derive", version = "=2.6.0" } async-graphql-derive = { path = "derive", version = "=2.6.0" }
@ -57,6 +39,8 @@ spin = "0.7.0"
thiserror = "1.0.21" thiserror = "1.0.21"
static_assertions = "1.1.0" static_assertions = "1.1.0"
http = "0.2.3" http = "0.2.3"
multer = "1.2.2"
tempfile = "3.1.0"
# Feature optional dependencies # Feature optional dependencies
bson = { version = "1.0.0", optional = true } bson = { version = "1.0.0", optional = true }
@ -71,10 +55,8 @@ uuid = { version = "0.8.1", optional = true, features = ["v4", "serde"] }
# Non-feature optional dependencies # Non-feature optional dependencies
blocking = { version = "1.0.0", optional = true } blocking = { version = "1.0.0", optional = true }
lru = { version = "0.6.0", optional = true } lru = { version = "0.6.0", optional = true }
multer = { version = "1.2.2", optional = true }
num-traits = { version = "0.2.12", optional = true } num-traits = { version = "0.2.12", optional = true }
sha2 = { version = "0.9.1", optional = true } sha2 = { version = "0.9.1", optional = true }
tempfile = { version = "3.1.0", optional = true }
futures-timer = { version = "3.0.2", optional = true } futures-timer = { version = "3.0.2", optional = true }
futures-channel = { version = "0.3.8", optional = true } futures-channel = { version = "0.3.8", optional = true }
@ -83,7 +65,8 @@ tokio = { version = "1.3.0", features = ["macros", "rt", "sync", "time"] }
futures-channel = "0.3.8" futures-channel = "0.3.8"
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["nightly"] all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[workspace] [workspace]
members = [ members = [

View File

@ -58,6 +58,24 @@ This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in
* Batch Queries * Batch Queries
* Apollo Persisted Queries * Apollo Persisted Queries
## Crate features
This crate offers the following features, all of which are not activated by default:
- `apollo_tracing`: Enable the [Apollo tracing extension](extensions/struct.ApolloTracing.html).
- `apollo_persisted_queries`: Enable the [Apollo persisted queries extension](extensions/apollo_persisted_queries/struct.ApolloPersistedQueries.html).
- `log`: Enable the [logger extension](extensions/struct.Logger.html).
- `tracing`: Enable the [tracing extension](extensions/struct.Tracing.html).
- `opentelemetry`: Enable the [OpenTelemetry extension](extensions/struct.OpenTelemetry.html).
- `unblock`: Support [asynchronous reader for Upload](types/struct.Upload.html)
- `bson`: Integrate with the [`bson` crate](https://crates.io/crates/bson).
- `chrono`: Integrate with the [`chrono` crate](https://crates.io/crates/chrono).
- `chrono-tz`: Integrate with the [`chrono-tz` crate](https://crates.io/crates/chrono-tz).
- `url`: Integrate with the [`url` crate](https://crates.io/crates/url).
- `uuid`: Integrate with the [`uuid` crate](https://crates.io/crates/uuid).
- `string_number`: Enable the [StringNumber](types/struct.StringNumber.html).
- `dataloader`: Support [DataLoader](dataloader/struct.DataLoader.html).
## Examples ## Examples
All examples are in the [sub-repository](https://github.com/async-graphql/examples), located in the examples directory. All examples are in the [sub-repository](https://github.com/async-graphql/examples), located in the examples directory.
@ -69,30 +87,6 @@ git submodule update # update the examples repo
cd examples && cargo run --bin [name] cd examples && cargo run --bin [name]
``` ```
## Benchmark
Ensure that there is no CPU-heavy process in background!
```shell script
cd benchmark
#measure all with system malloc
cargo bench
#measure only chat run
cargo bench -- "chat run"
#measure all with jemalloc
cargo bench --features jemalloc
#measure only simple run with jemalloc
cargo bench --features jemalloc -- "simple run"
```
Now HTML report is available at `benchmark/target/criterion/report`
Read more here: https://bheisler.github.io/criterion.rs/book/criterion_rs.html
## Integrations ## Integrations
* Actix-web [async-graphql-actix-web](https://crates.io/crates/async-graphql-actix-web) * Actix-web [async-graphql-actix-web](https://crates.io/crates/async-graphql-actix-web)

View File

@ -124,7 +124,7 @@ pub trait Loader<K: Send + Hash + Eq + Clone + 'static>: Send + Sync + 'static {
/// Data loader. /// Data loader.
/// ///
/// Reference: https://github.com/facebook/dataloader /// Reference: <https://github.com/facebook/dataloader>
pub struct DataLoader<T> { pub struct DataLoader<T> {
requests: Mutex<FnvHashMap<TypeId, Box<dyn Any + Sync + Send>>>, requests: Mutex<FnvHashMap<TypeId, Box<dyn Any + Sync + Send>>>,
delay: Duration, delay: Duration,

View File

@ -233,8 +233,6 @@ pub enum ParseRequestError {
/// The request's multipart data was invalid. /// The request's multipart data was invalid.
#[error("Invalid multipart data")] #[error("Invalid multipart data")]
#[cfg(feature = "multipart")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "multipart")))]
InvalidMultipart(multer::Error), InvalidMultipart(multer::Error),
/// Missing "operators" part for multipart request. /// Missing "operators" part for multipart request.
@ -262,7 +260,6 @@ pub enum ParseRequestError {
UnsupportedBatch, UnsupportedBatch,
} }
#[cfg(feature = "multipart")]
impl From<multer::Error> for ParseRequestError { impl From<multer::Error> for ParseRequestError {
fn from(err: multer::Error) -> Self { fn from(err: multer::Error) -> Self {
match err { match err {

View File

@ -53,7 +53,7 @@ impl CacheStorage for LruCacheStorage {
/// Apollo persisted queries extension. /// Apollo persisted queries extension.
/// ///
/// [Reference](https://www.apollographql.com/docs/react/api/link/persisted-queries/) /// [Reference](https://www.apollographql.com/docs/react/api/link/persisted-queries/)
#[cfg_attr(feature = "nightly", doc(cfg(feature = "apollo_persisted_queries")))] #[cfg_attr(docrs, doc(cfg(feature = "apollo_persisted_queries")))]
pub struct ApolloPersistedQueries<T>(T); pub struct ApolloPersistedQueries<T>(T);
impl<T: CacheStorage> ApolloPersistedQueries<T> { impl<T: CacheStorage> ApolloPersistedQueries<T> {

View File

@ -53,7 +53,7 @@ impl Serialize for ResolveStat {
/// have access to performance traces alongside the data returned by your query. /// have access to performance traces alongside the data returned by your query.
/// It's already supported by `Apollo Engine`, and we're excited to see what other kinds of /// It's already supported by `Apollo Engine`, and we're excited to see what other kinds of
/// integrations people can build on top of this format. /// integrations people can build on top of this format.
#[cfg_attr(feature = "nightly", doc(cfg(feature = "apollo_tracing")))] #[cfg_attr(docrs, doc(cfg(feature = "apollo_tracing")))]
pub struct ApolloTracing; pub struct ApolloTracing;
impl ExtensionFactory for ApolloTracing { impl ExtensionFactory for ApolloTracing {

View File

@ -7,7 +7,7 @@ use crate::parser::types::{ExecutableDocument, OperationType, Selection};
use crate::{PathSegment, ServerError, Variables}; use crate::{PathSegment, ServerError, Variables};
/// Logger extension /// Logger extension
#[cfg_attr(feature = "nightly", doc(cfg(feature = "log")))] #[cfg_attr(docrs, doc(cfg(feature = "log")))]
pub struct Logger; pub struct Logger;
impl ExtensionFactory for Logger { impl ExtensionFactory for Logger {

View File

@ -29,7 +29,7 @@ const KEY_DEPTH: Key = Key::from_static_str("graphql.depth");
/// OpenTelemetry extension /// OpenTelemetry extension
#[derive(Default)] #[derive(Default)]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "opentelemetry")))] #[cfg_attr(docrs, doc(cfg(feature = "opentelemetry")))]
pub struct OpenTelemetry<T, U> { pub struct OpenTelemetry<T, U> {
tracer: T, tracer: T,
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -8,7 +8,7 @@ use crate::{ServerError, ValidationResult, Variables};
/// Tracing extension configuration for each request. /// Tracing extension configuration for each request.
#[derive(Default)] #[derive(Default)]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "tracing")))] #[cfg_attr(docrs, doc(cfg(feature = "tracing")))]
pub struct TracingConfig { pub struct TracingConfig {
/// Use a span as the parent node of the entire query. /// Use a span as the parent node of the entire query.
parent: Option<Span>, parent: Option<Span>,
@ -67,7 +67,7 @@ fn resolve_span_id(resolver_id: usize) -> usize {
/// }); /// });
/// ``` /// ```
#[derive(Default)] #[derive(Default)]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "tracing")))] #[cfg_attr(docrs, doc(cfg(feature = "tracing")))]
pub struct Tracing; pub struct Tracing;
impl ExtensionFactory for Tracing { impl ExtensionFactory for Tracing {

View File

@ -1,7 +1,6 @@
//! A helper module that supports HTTP //! A helper module that supports HTTP
mod graphiql_source; mod graphiql_source;
#[cfg(feature = "multipart")]
mod multipart; mod multipart;
mod playground_source; mod playground_source;
mod websocket; mod websocket;
@ -11,13 +10,10 @@ use futures_util::io::{AsyncRead, AsyncReadExt};
use crate::{BatchRequest, ParseRequestError, Request}; use crate::{BatchRequest, ParseRequestError, Request};
pub use graphiql_source::graphiql_source; pub use graphiql_source::graphiql_source;
#[cfg(feature = "multipart")]
pub use multipart::MultipartOptions; pub use multipart::MultipartOptions;
pub use playground_source::{playground_source, GraphQLPlaygroundConfig}; pub use playground_source::{playground_source, GraphQLPlaygroundConfig};
pub use websocket::{Protocols as WebSocketProtocols, WebSocket, WsMessage}; pub use websocket::{Protocols as WebSocketProtocols, WebSocket, WsMessage};
#[cfg(feature = "multipart")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "multipart")))]
/// Receive a GraphQL request from a content type and body. /// Receive a GraphQL request from a content type and body.
pub async fn receive_body( pub async fn receive_body(
content_type: Option<impl AsRef<str>>, content_type: Option<impl AsRef<str>>,
@ -29,8 +25,6 @@ pub async fn receive_body(
.into_single() .into_single()
} }
#[cfg(feature = "multipart")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "multipart")))]
/// Receive a GraphQL request from a content type and body. /// Receive a GraphQL request from a content type and body.
pub async fn receive_batch_body( pub async fn receive_batch_body(
content_type: Option<impl AsRef<str>>, content_type: Option<impl AsRef<str>>,

View File

@ -13,7 +13,6 @@ use crate::{BatchRequest, ParseRequestError, UploadValue};
/// Options for `receive_multipart`. /// Options for `receive_multipart`.
#[derive(Default, Clone, Copy)] #[derive(Default, Clone, Copy)]
#[non_exhaustive] #[non_exhaustive]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "multipart")))]
pub struct MultipartOptions { pub struct MultipartOptions {
/// The maximum file size. /// The maximum file size.
pub max_file_size: Option<usize>, pub max_file_size: Option<usize>,

View File

@ -25,13 +25,13 @@ pub enum WsMessage {
} }
impl WsMessage { impl WsMessage {
/// Returns the contained [`Text`] value, consuming the `self` value. /// Returns the contained [WsMessage::Text] value, consuming the `self` value.
/// ///
/// Because this function may panic, its use is generally discouraged. /// Because this function may panic, its use is generally discouraged.
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if the self value not equals [`Text`]. /// Panics if the self value not equals [WsMessage::Text].
pub fn unwrap_text(self) -> String { pub fn unwrap_text(self) -> String {
match self { match self {
Self::Text(text) => text, Self::Text(text) => text,
@ -39,13 +39,13 @@ impl WsMessage {
} }
} }
/// Returns the contained [`Close`] value, consuming the `self` value. /// Returns the contained [WsMessage::Close] value, consuming the `self` value.
/// ///
/// Because this function may panic, its use is generally discouraged. /// Because this function may panic, its use is generally discouraged.
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if the self value not equals [`Close`]. /// Panics if the self value not equals [WsMessage::Close].
pub fn unwrap_close(self) -> (u16, String) { pub fn unwrap_close(self) -> (u16, String) {
match self { match self {
Self::Close(code, msg) => (code, msg), Self::Close(code, msg) => (code, msg),

View File

@ -54,22 +54,15 @@
//! * Batch Queries //! * Batch Queries
//! * Apollo Persisted Queries //! * Apollo Persisted Queries
//! //!
//! # Crate features //! ## Crate features
//! //!
//! This crate offers the following features, all of which are activated by default: //! This crate offers the following features, all of which are not activated by default:
//!
//! **I recommend that you always turn off all features and turn them on only
//! when needed, which can significantly increase compilation speed.**
//!
//! ```toml
//! async-graphql = { version = "*", default-features = false }
//! ```
//! //!
//! - `apollo_tracing`: Enable the [Apollo tracing extension](extensions/struct.ApolloTracing.html). //! - `apollo_tracing`: Enable the [Apollo tracing extension](extensions/struct.ApolloTracing.html).
//! - `apollo_persisted_queries`: Enable the [Apollo persisted queries extension](extensions/apollo_persisted_queries/struct.ApolloPersistedQueries.html). //! - `apollo_persisted_queries`: Enable the [Apollo persisted queries extension](extensions/apollo_persisted_queries/struct.ApolloPersistedQueries.html).
//! - `log`: Enable the [logger extension](extensions/struct.Logger.html). //! - `log`: Enable the [logger extension](extensions/struct.Logger.html).
//! - `tracing`: Enable the [tracing extension](extensions/struct.Tracing.html). //! - `tracing`: Enable the [tracing extension](extensions/struct.Tracing.html).
//! - `multipart`: Support [sending files over HTTP multipart](http/fn.receive_body.html). //! - `opentelemetry`: Enable the [OpenTelemetry extension](extensions/struct.OpenTelemetry.html).
//! - `unblock`: Support [asynchronous reader for Upload](types/struct.Upload.html) //! - `unblock`: Support [asynchronous reader for Upload](types/struct.Upload.html)
//! - `bson`: Integrate with the [`bson` crate](https://crates.io/crates/bson). //! - `bson`: Integrate with the [`bson` crate](https://crates.io/crates/bson).
//! - `chrono`: Integrate with the [`chrono` crate](https://crates.io/crates/chrono). //! - `chrono`: Integrate with the [`chrono` crate](https://crates.io/crates/chrono).
@ -164,7 +157,7 @@
#![allow(clippy::trivially_copy_pass_by_ref)] #![allow(clippy::trivially_copy_pass_by_ref)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![cfg_attr(feature = "nightly", feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))]
mod base; mod base;
mod error; mod error;
@ -178,7 +171,7 @@ mod validation;
pub mod context; pub mod context;
#[cfg(feature = "dataloader")] #[cfg(feature = "dataloader")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "dataloader")))] #[cfg_attr(docrs, doc(cfg(feature = "dataloader")))]
pub mod dataloader; pub mod dataloader;
pub mod extensions; pub mod extensions;
pub mod guard; pub mod guard;
@ -683,7 +676,7 @@ pub use async_graphql_derive::InputObject;
/// | name | Object name | string | Y | /// | name | Object name | string | Y |
/// | rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y | /// | rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
/// | rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y | /// | rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
/// | field | Fields of this Interface | [InterfaceField] | N | /// | field | Fields of this Interface | InterfaceField | N |
/// | extends | Add fields to an entity that's defined in another service | bool | Y | /// | extends | Add fields to an entity that's defined in another service | bool | Y |
/// | visible | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y | /// | visible | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y | /// | visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
@ -698,7 +691,7 @@ pub use async_graphql_derive::InputObject;
/// | desc | Field description | string | Y | /// | desc | Field description | string | Y |
/// | deprecation | Field deprecated | bool | Y | /// | deprecation | Field deprecated | bool | Y |
/// | deprecation | Field deprecation reason | string | Y | /// | deprecation | Field deprecation reason | string | Y |
/// | arg | Field arguments | [InterfaceFieldArgument] | Y | /// | arg | Field arguments | InterfaceFieldArgument | Y |
/// | external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y | /// | external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
/// | provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y | /// | provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
/// | requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y | /// | requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |

View File

@ -7,7 +7,7 @@ use crate::ID;
/// Cursor type /// Cursor type
/// ///
/// A custom scalar that serializes as a string. /// A custom scalar that serializes as a string.
/// https://relay.dev/graphql/connections.htm#sec-Cursor /// <https://relay.dev/graphql/connections.htm#sec-Cursor>
pub trait CursorType: Sized { pub trait CursorType: Sized {
/// Error type for `decode_cursor`. /// Error type for `decode_cursor`.
type Error: Display; type Error: Display;

View File

@ -8,7 +8,7 @@ use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value};
/// A numeric value represented by a string. /// A numeric value represented by a string.
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
#[serde(transparent)] #[serde(transparent)]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "string_number")))] #[cfg_attr(docrs, doc(cfg(feature = "string_number")))]
pub struct StringNumber<T: Num + Display>(pub T); pub struct StringNumber<T: Num + Display>(pub T);
#[Scalar(internal)] #[Scalar(internal)]

View File

@ -40,7 +40,7 @@ impl UploadValue {
} }
#[cfg(feature = "unblock")] #[cfg(feature = "unblock")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "unblock")))] #[cfg_attr(docrs, doc(cfg(feature = "unblock")))]
/// Convert to a `AsyncRead`. /// Convert to a `AsyncRead`.
pub fn into_async_read(self) -> impl AsyncRead + Sync + Send + 'static { pub fn into_async_read(self) -> impl AsyncRead + Sync + Send + 'static {
blocking::Unblock::new(self.content) blocking::Unblock::new(self.content)