NiQin (blog: 泥芹) shared the aphorism --
I returned and saw under the sun, that the race is not to the swift, nor the battle to the strong, neither yet bread to the wise, nor yet riches to men of understanding, nor yet favour to men of skill; but time and chance happeneth to them all. -- 《圣经》

[GraphQL] 基于 actix-web + async-graphql + rbatis + postgresql / mysql 构建异步 Rust GraphQL 服务(2) - 查询服务

💥 内容涉及著作权,均归属作者本人。若非作者注明,默认欢迎转载:请注明出处,及相关链接。

Summary: 本文中,我们将开启基于 actix-web 和 async-graphql 构建异步 Rust GraphQL 服务的历程。本章主要是 GraphQL 查询服务,包括如下内容: 1、构建 GraphQL Schema; 2、整合 actix-web 和 async-graphql; 3、验证 query 服务; 4、连接 mysql; 5、提供 query 服务。

Topics: rust graphql async-graphql mysql actix-web rbatis graphql-查询

上一篇文章中,我们对后端基础工程进行了初始化,未有进行任何代码编写。本文中,我们将不再进行技术选型和优劣对比,直接基于 actix-web 和 async-graphql 构建异步 Rust GraphQL 服务的历程。本章主要是 GraphQL 查询服务,包括如下内容:

1、构建 GraphQL Schema;

2、整合 actix-web 和 async-graphql;

3、验证 query 服务;

4、连接 mysql;

5、提供 query 服务。

构建 GraphQL Schema

首先,让我们将 GraphQL 服务相关的代码都放到一个模块中。为了避免下文啰嗦,我称其为 GraphQL 总线。

cd ./actix-web-async-graphql/backend/src
mkdir gql
cd ./gql
touch mod.rs queries.rs mutations.rs

构建一个查询示例

  • 首先,我们构建一个不连接数据库的查询示例:通过一个函数进行求合运算,将其返回给 graphql 查询服务。此实例改编自 async-graphql 文档,仅用于验证环境配置,实际环境没有意义。

下面代码中,注意变更 EmptyMutation 和订阅 EmptySubscription 都是空的,甚至 mutations.rs 文件都是空白,未有任何代码,仅为验证服务器正确配置。

下面,我们需要编写代码。思路如下:

编写求和实例,作为 query 服务

queries.rs 文件中,写入以下代码:


pub struct QueryRoot;

#[async_graphql::Object]
impl QueryRoot {
    async fn add(&self, a: i32, b: i32) -> i32 {
        a + b
    }
}

mod.rs 中:构建 Schema,并编写请求处理(handler)函数

  • 通过 async-graphql SchemaBuilder,构建要在 actix-web 中使用的 GraphQL Schema,并接入我们自己的查询、变更,以及订阅服务。
  • 目前,我们首先要进行 actix-webasync-graphql 的集成验证,所以仅有求和作为查询服务,变更和订阅服务都是空的。
  • 同时,我们要进行 actix-web 中的请求处理(handler)函数的编写。

actix-web 的请求处理函数中,请求为 HttpRequest 类型,响应类型则是 HttpResponse。而 async-graphql 在执行 GraphQL 服务时,请求类型和返回类型与 actix-web 的并不同,需要进行封装处理。

async-graphql 官方提供了 actix-web 与 async-graphql 的集成 crate async-graphql-actix-web,功能很全。我们直接使用,通过 cargo add async-graphql-actix-web 命令添加到依赖项。然后,填入具体代码如下:

pub mod mutations;
pub mod queries;

use actix_web::{web, HttpResponse, Result};
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig};
use async_graphql::{EmptyMutation, EmptySubscription, Schema};
use async_graphql_actix_web::{Request, Response};

use crate::gql::queries::QueryRoot;

// `ActixSchema` 类型定义,项目中可以统一放置在一个共用文件中。
// 但和 `actix-web` 和 `tide` 框架不同,无需放入应用程序`状态(State)`
// 所以此 `Schema` 类型仅是为了代码清晰易读,使用位置并不多,我们直接和构建函数一起定义。
// 或者,不做此类型定义,直接作为构建函数的返回类型。
type ActixSchema = Schema<
    queries::QueryRoot,
    async_graphql::EmptyMutation,
    async_graphql::EmptySubscription,
>;

pub async fn build_schema() -> ActixSchema {
    // The root object for the query and Mutatio, and use EmptySubscription.
    // Add global sql datasource  in the schema object.
    Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish()
}

pub async fn graphql(schema: web::Data<ActixSchema>, req: Request) -> Response {
    schema.execute(req.into_inner()).await.into()
}

pub async fn graphiql() -> Result<HttpResponse> {
    Ok(HttpResponse::Ok().content_type("text/html; charset=utf-8").body(
        playground_source(
            GraphQLPlaygroundConfig::new("/graphql").subscription_endpoint("/graphql"),
        ),
    ))
}

上面的示例代码中,函数 graphqlgraphiql 作为 actix-web 服务器的请求处理程序,因此必须返回 actix_web::HttpResponse

actix-web 开发本文不是重点,请参阅 actix-web 中文文档,很短时间即可掌握。

整合 actix-web 和 async-graphql

接下来,我们要进行 actix-web 服务器主程序开发和启动。进入 ./backend/src 目录,迭代 main.rs 文件:

mod gql;

use actix_web::{guard, web, App, HttpServer};

use crate::gql::{build_schema, graphql, graphiql};

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    let schema = build_schema().await;

    println!("GraphQL UI: http://127.0.0.1:8080");

    HttpServer::new(move || {
        App::new()
            .data(schema.clone())
            .service(web::resource("/graphql").guard(guard::Post()).to(graphql))
            .service(web::resource("/graphiql").guard(guard::Get()).to(graphiql))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

本段代码中,我们直接在 App 构建器中加入 schema,以及对于 graphqlgraphiql 这两个请求处理函数,我们也是在 App 构建器中逐次注册。这种方式虽然没有问题,但对于一个应用的主程序 main.rs 来讲,精简一些更易于阅读和维护。所以我们下一篇文章中对此迭代,通过 ServiceConfig 进行注册。

验证 query 服务

启动 actix-web 服务

以上,一个基础的基于 Rust 技术栈的 GraphQL 服务器已经开发成功了。我们验证以下是否正常,请执行——

cargo run

更推荐您使用我们前一篇文章中安装的 cargo watch 来启动服务器,这样后续代码的修改,可以自动部署,无需您反复对服务器进行停止和启动操作。

cargo watch -x "run"

但遗憾的是——此时,你会发现服务器无法启动,因为上面的代码中,我们使用了 #[actix_rt::main] 此类的 Rust 属性标记。编译器会提示如下错误信息:

error[E0433]: failed to resolve: use of undeclared crate or module `actix_rt`
 --> backend\src\main.rs:7:3
  |
7 | #[actix_rt::main]
  |   ^^^^^^^^ use of undeclared crate or module `actix_rt`
……
……
error[E0752]: `main` function is not allowed to be `async`
 --> backend\src\main.rs:8:1
  |
8 | async fn main() -> std::io::Result<()> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0277, E0433, E0752.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `backend`

根据编译器提示,我们执行 cargo add actix-rt,然后重新运行。但很遗憾,仍然会报错:

thread 'main' panicked at 'System is not running', ……\actix-rt-1.1.1\src\system.rs:78:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

并且,我们查看 backend/Cargo.toml 文件时会发现,我们通过 cargo add 添加的依赖项是最新版,actix-rt = "2.2.0",但此处错误信息却是 actix-rt-1.1.1\src\system.rs:78:21。这是因为 actix-web 3.3.2,可以一起正常工作的 actix-rt 最高版本是 1.1.1。如果你想使用 actix-rt = "2.2.0",需要使用 actix-web 的测试版本,如下面配置:

……
actix = "0.11.0-beta.2"
actix-web = "4.0.0-beta.3"
actix-rt = "2.0.2"
……

我们的实践是为了生产环境使用,不尝鲜了。最终,我们更改 backend/Cargo.toml 文件如下:

[package]
name = "backend"
version = "0.1.0"
authors = ["zzy <linshi@budshome.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "3.3.2"
actix-rt = "1.1.1"

async-graphql = { version = "2.8.2", features = ["chrono"] }
async-graphql-actix-web = "2.8.2"
rbatis = { version = "1.8.83", default-features = false, features = ["mysql", "postgres"] }

请注意,不是根目录 actix-web-async-graphql/Cargo.toml 文件。

再次执行 cargo run 命令,您会发现服务器已经启动成功。

执行 GraphQL 查询

请打开您的浏览器,输入 http://127.0.0.1:8080/graphiql,您会看到如下界面(点击右侧卡片 docs 和 schema 查看详细):

graphiql

如图中示例,在左侧输入:

query {
  add(a: 110, b: 11)
}

右侧的返回结果为:

{
  "data": {
    "add": 121
  }
}

基础的 GraphQL 查询服务成功!

连接 MySql

创建 MySql 数据池

为了做到代码仓库风格的统一,以及扩展性。目前即使只需要连接 MySql 数据库,我们也将其放到一个模块中。

cd ./actix-web-async-graphql/backend/src
mkdir dbs
touch ./dbs/mod.rs ./dbs/mysql.rs

mysql.rs 中,编写如下代码:

use rbatis::core::db::DBPoolOptions;
use rbatis::rbatis::Rbatis;

// 对于常量,应当统一放置
// 下一篇重构中,我们再讨论不同的方式
pub const MYSQL_URL: &'static str =
    "mysql://root:mysql@localhost:3306/budshome";

pub async fn my_pool() -> Rbatis {
    let rb = Rbatis::new();

    let mut opts = DBPoolOptions::new();
    opts.max_connections = 100;

    rb.link_opt(MYSQL_URL, &opts).await.unwrap();

    rb
}

mod.rs 中,编写如下代码:

// pub mod postgres;
pub mod mysql;

创建数据表及数据

在 mysql 中,创建 user 表,并构造几条数据,示例数据如下:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(0) UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `cred` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'ok@budshome.com', '我谁24ok32', '5ff82b2c0076cc8b00e5cddb');
INSERT INTO `user` VALUES (2, 'oka@budshome.com', '我s谁24ok32', '5ff83f4b00e8fda000e5cddc');
INSERT INTO `user` VALUES (3, 'oka2@budshome.com', '我2s谁24ok32', '5ffd710400b6b84e000349f8');

SET FOREIGN_KEY_CHECKS = 1;
  • id 是由 mysql 自动产生的,且递增;
  • cred 是使用 PBKDF2 对用户密码进行加密(salt)和散列(hash)运算后产生的密码,后面会有详述。此处,请您随意。

提供 query 服务

Schema 中添加 MySql 数据池

前文小节我们创建了 MySql 数据池,欲在 async-graphql 中是获取和使用 MySql 数据池,有如下方法——

  1. 作为 async-graphql 的全局数据;
  2. 作为 actix-web 的应用程序数据,优势是可以进行原子操作;
  3. 使用 lazy-static,优势是获取方便,简单易用。

如果不作前后端分离,为了方便前端的数据库操作,那么 2 和 3 是比较推荐的,特别是使用 crate lazy-static,存取方便,简单易用。rbatis 的官方实例,以及笔者看到其它开源 rust-web 项目,都采用 lazy-static。因为 rbatis 实现了 Send + Sync,是线程安全的,无需担心线程竞争。

虽然 2 和 3 方便、简单,以及易用。但是本应用中,我们仅需要 actix-web 作为一个服务器提供 http 服务,MySql 数据池也仅是为 async-graphql 使用。因此,我采用作为 async-graphql 的全局数据,将其构建到 Schema 中。

笔者仅是简单使用,如果您有深入的见解,欢迎您指导(微信号 yupen-com,或者页底邮箱)。

基于上述思路,我们迭代 backend/src/gql/mod.rs 文件:

pub mod mutations;
pub mod queries;

use actix_web::{web, HttpResponse, Result};
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig};
use async_graphql::{EmptyMutation, EmptySubscription, Schema};
use async_graphql_actix_web::{Request, Response};

use crate::dbs::mysql::my_pool;
use crate::gql::queries::QueryRoot;

type ActixSchema = Schema<
    queries::QueryRoot,
    async_graphql::EmptyMutation,
    async_graphql::EmptySubscription,
>;

pub async fn build_schema() -> ActixSchema {
    // 获取 MySql 数据池后,可以将其增加到:
    // 1. 作为 async-graphql 的全局数据;
    // 2. 作为 actix-web 的应用程序数据,优势是可以进行原子操作;
    // 3. 使用 lazy-static.rs
    let my_pool = my_pool().await;

    // The root object for the query and Mutatio, and use EmptySubscription.
    // Add global mysql pool  in the schema object.
    Schema::build(QueryRoot, EmptyMutation, EmptySubscription)
        .data(my_pool)
        .finish()
}

pub async fn graphql(schema: web::Data<ActixSchema>, req: Request) -> Response {
    schema.execute(req.into_inner()).await.into()
}

pub async fn graphiql() -> Result<HttpResponse> {
    Ok(HttpResponse::Ok().content_type("text/html; charset=utf-8").body(
        playground_source(
            GraphQLPlaygroundConfig::new("/graphql")
                .subscription_endpoint("/graphql"),
        ),
    ))
}

实现查询服务,自 MySql user 表查询所有用户

增加 users 模块,及分层阐述

一个完整的 GraphQL 查询服务,在本应用项目——注意,非 actix-web 或者 GraphQL 技术分层——我们可以简单将其分为三层:

  • actix-web handler:发起一次 GraphQL 请求,通知 GraphQL 总线执行 GraphQL service 调用,以及接收和处理响应;
  • GraphQL 总线:分发 GraphQL service 调用;
  • services:负责执行具体的查询服务,从 MySql 数据表获取数据,并封装到 model 中;

基于上述思路,我们想要开发一个查询所有用户的 GraphQL 服务,需要增加 users 模块,并创建如下文件:

cd ./backend/src
mkdir users
cd users
touch mod.rs models.rs services.rs

至此,本篇文章的所有文件已经创建,先让我们查看一下总体的 backend 工程结构,如下图所示:

backend 完成文件结构

其中 users/mod.rs 文件内容为:

pub mod models;
pub mod services;

我们也需要将 users 模块添加到 main.rs 中:

mod gql;
mod dbs;
mod users;

use actix_web::{guard, web, App, HttpServer};

use crate::gql::{build_schema, graphql, graphiql};

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    let schema = build_schema().await;

    println!("GraphQL UI: http://127.0.0.1:8080");

    HttpServer::new(move || {
        App::new()
            .data(schema.clone())
            .service(web::resource("/graphql").guard(guard::Post()).to(graphql))
            .service(
                web::resource("/graphiql").guard(guard::Get()).to(graphiql),
            )
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

编写 User 模型

users/models.rs 文件中添加:

use serde::{Serialize, Deserialize};

#[rbatis::crud_enable]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct User {
    pub id: i32,
    pub email: String,
    pub username: String,
    pub cred: String,
}

#[async_graphql::Object]
impl User {
    pub async fn id(&self) -> i32 {
        self.id
    }

    pub async fn email(&self) -> &str {
        self.email.as_str()
    }

    pub async fn username(&self) -> &str {
        self.username.as_str()
    }
}

上述代码中,User 结构体中定义的字段类型为 String,但结构体实现中返回为 &str,这是因为 Rust 中 String 未有默认实现 copy trait。如果您希望结构体实现中返回 String,可以通过 clone() 方法实现:

    pub async fn email(&self) -> String {
        self.email.clone()
    }

您使用的 IDE 比较智能,或许会有报错,先不要管,我们后面一并处理。

编写 service

users/services.rs 文件中添加代码,这次比 MongoDB 少了很多代码。如下:

use async_graphql::{Error, ErrorExtensions};
use rbatis::rbatis::Rbatis;
use rbatis::crud::CRUD;

use crate::users::models::User;

pub async fn all_users(
    my_pool: &Rbatis,
) -> std::result::Result<Vec<User>, async_graphql::Error> {
    let users = my_pool.fetch_list::<User>("").await.unwrap();

    if users.len() > 0 {
        Ok(users)
    } else {
        Err(Error::new("1-all-users")
            .extend_with(|_, e| e.set("details", "No records")))
    }
}

您使用的 IDE 比较智能,或许会有报错,先不要管,我们后面一并处理。

在 GraphQL 总线中调用 service

迭代 gql/queries.rs 文件,最终为:

use async_graphql::Context;
use rbatis::rbatis::Rbatis;

use crate::users::{self, models::User};

pub struct QueryRoot;

#[async_graphql::Object]
impl QueryRoot {
    // Get all Users,
    async fn all_users(
        &self,
        ctx: &Context<'_>,
    ) -> std::result::Result<Vec<User>, async_graphql::Error> {
        let my_pool = ctx.data_unchecked::<Rbatis>();
        users::services::all_users(my_pool).await
    }
}

Okay,如果您使用的 IDE 比较智能,可以看到现在已经是满屏的红、黄相配了。代码是没有问题的,我们只是缺少几个使用到的 crate。

  • 首先,执行命令:
cargo add serde
  • 其次,因为我们使用到了 serde crate 的 derive trait,因此需要迭代 backend/Cargo.toml 文件,最终版本为:
[package]
name = "backend"
version = "0.1.0"
authors = ["zzy <linshi@budshome.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "3.3.2"
actix-rt = "1.1.1"

async-graphql = { version = "2.8.2", features = ["chrono"] }
async-graphql-actix-web = "2.8.2"
rbatis = { version = "1.8.83", default-features = false, features = ["mysql", "postgres"] }

serde = { version = "1.0", features = ["derive"] }

现在,重新运行 cargo build,可以发现红、黄错误已经消失殆尽了。执行 cargo watch -x "run" 命令会发现启动成功。

最后,我们来执行 GraphQL 查询,看看是否取出了 MySql 中 user 表的所有数据。

左侧输入:

# Write your query or mutation here
query {
  allUsers {
    id
    email
    username
  }
}

右侧返回结果依赖于您在数据表中添加了多少条数据,如我的查询结果为:

{
  "data": {
    "allUsers": [
      {
        "email": "ok@budshome.com",
        "id": 1,
        "username": "我谁24ok32"
      },
      {
        "email": "oka@budshome.com",
        "id": 2,
        "username": "我s谁24ok32"
      },
      {
        "email": "oka2@budshome.com",
        "id": 3,
        "username": "我2s谁24ok32"
      }
      ……
      ……
    ]
  }
}

好的,以上就是一个完成的 GraphQL 查询服务。

实例源码仓库在 github,欢迎您共同完善。

下篇摘要

目前我们成功开发了一个基于 Rust 技术栈的 GraphQL 查询服务,但本例代码是不够满意的,如冗长的返回类型 std::result::Result<Vec<User>, async_graphql::Error>,如太多的魔术代码。

下篇中,我们先不进行 GraphQL mutation 的开发。我将对代码进行重构——

  • 应用配置文件;
  • 代码抽象。

谢谢您的阅读,欢迎交流(微信号 yupen-com,或者页底邮箱)。


Related Articles

  1. [Rust] RustHub.org:基于 Rust-Web 技术栈,及 image-rs、fluent-rs、rhai-script ……
  2. [WebAssembly] yew SSR 服务器端渲染
  3. [Rust] async-std 创建者对于最近“项目是否已死?”,移除对其支持等的答复
  4. [Rust] Rust 1.56.0 版本和 Rust 2021 版次发布,新特性一览,及项目的迁移、升级
  5. [WebAssembly] Rust 和 Wasm 的融合,使用 yew 构建 WebAssembly 博客应用的体验报告
  6. [Rust] Rust 官方周报 399 期(2021-07-14)
  7. [WebAssembly] Rust 和 Wasm 的融合,使用 yew 构建 web 前端(5)- 构建 HTTP 请求、与外部服务器通信的两种方法
  8. [Rust] Rust 官方周报 398 期(2021-07-07)
  9. [Rust] Rust 官方周报 397 期(2021-06-30)
  10. [Rust] Rust 官方周报 396 期(2021-06-23)
  11. [Rust] Rust 官方周报 395 期(2021-06-16)
  12. [Rust] Rust 1.53.0 明日发布,关键新特性一瞥
  13. [Rust] 使用 tide、handlebars、rhai、graphql 开发 Rust web 前端(3)- rhai 脚本、静态/资源文件、环境变量等
  14. [Rust] 使用 tide、handlebars、rhai、graphql 开发 Rust web 前端(2)- 获取并解析 GraphQL 数据
  15. [Rust] 使用 tide、handlebars、rhai、graphql 开发 Rust web 前端(1)- crate 选择及环境搭建
  16. [Rust] Rust 官方周报 394 期(2021-06-09)
  17. [Rust] Rust web 前端库/框架评测,以及和 js 前端库/框架的比较
  18. [WebAssembly] Rust 和 Wasm 的融合,使用 yew 构建 web 前端(4)- 获取 GraphQL 数据并解析
  19. [WebAssembly] Rust 和 Wasm 的融合,使用 yew 构建 web 前端(3)- 资源文件及小重构
  20. [WebAssembly] Rust 和 Wasm 的融合,使用 yew 构建 WebAssembly 标准的 web 前端(2)- 组件和路由
  21. [WebAssembly] Rust 和 Wasm 的融合,使用 yew 构建 WebAssembly 标准的 web 前端(1)- 起步及 crate 选择
  22. [Rust] Rust 官方周报 393 期(2021-06-02)
  23. [Rust] Rust 官方周报 392 期(2021-05-26)
  24. [Rust] Rust 中,对网址进行异步快照,并添加水印效果的实践
  25. [Rust] Rust 官方周报 391 期(2021-05-19)
  26. [Rust] Rust,风雨六载,砥砺奋进
  27. [Rust] 为什么我们应当将 Rust 用于嵌入式开发?
  28. [Rust] Rust 官方周报 390 期(2021-05-12)
  29. [Rust] Rust + Android 的集成开发设计
  30. [Rust] Rust 1.52.1 已正式发布,及其新特性详述
  31. [Rust] 让我们用 Rust 重写那些伟大的软件吧
  32. [Rust] Rust 1.52.0 已正式发布,及其新特性详述
  33. [Rust] Rust 官方周报 389 期(2021-05-05)
  34. [GraphQL] 基于 actix-web + async-graphql + rbatis + postgresql / mysql 构建异步 Rust GraphQL 服务(4) - 变更服务,以及小重构
  35. [Rust] Rust 1.52.0 稳定版预发布测试中,关键新特性一瞥
  36. [Rust] Rust 生态中,最不知名的贡献者和轶事
  37. [Rust] Rust 基金会迎来新的白金会员:Facebook
  38. [Rust] Rustup 1.24.1 已官宣发布,及其新特性详述
  39. [Rust] Rust 官方周报 388 期(2021-04-28)
  40. [Rust] Rust 官方周报 387 期(2021-04-21)
  41. [GraphQL] 构建 Rust 异步 GraphQL 服务:基于 tide + async-graphql + mongodb(4)- 变更服务,以及第二次重构
  42. [Rust] Rustup 1.24.0 已官宣发布,及其新特性详述
  43. [Rust] basedrop:Rust 生态中,适用于实时音频的垃圾收集器
  44. [Rust] Rust 编译器团队对成员 Aaron Hill 的祝贺
  45. [Rust] Jacob Hoffman-Andrews 加入 Rustdoc 团队
  46. [机器人] 为什么应将 Rust 引入机器人平台?以及机器人平台的 Rust 资源推荐
  47. [Rust] rust-lang.org、crates.io,以及 docs.rs 的管理,已由 Mozilla 转移到 Rust 基金会
  48. [Rust] Rust 官方周报 386 期(2021-04-14)
  49. [Rust] Rust 编译器(Compiler)团队 4 月份计划 - Rust Compiler April Steering Cycle
  50. [GraphQL] 基于 actix-web + async-graphql + rbatis + postgresql / mysql 构建异步 Rust GraphQL 服务(3) - 重构
  51. [Rust] 头脑风暴进行中:Async Rust 的未来熠熠生辉
  52. [GraphQL] 基于 actix-web + async-graphql + rbatis + postgresql / mysql 构建异步 Rust GraphQL 服务(2) - 查询服务
  53. [GraphQL] 基于 actix-web + async-graphql + rbatis + postgresql / mysql 构建异步 Rust GraphQL 服务 - 起步及 crate 选择
  54. [Rust] Rust 2021 版本特性预览,以及工作计划
  55. [Rust] Rust 用在生产环境的 42 家公司
  56. [Rust] 构建最精简的 Rust Docker 镜像
  57. [Rust] Rust 官方周报 385 期(2021-04-07)
  58. [Rust] 使用 Rust 做异步数据采集的实践
  59. [Rust] Android 支持 Rust 编程语言,以避免内存缺陷
  60. [Rust] Android 平台基础支持转向 Rust
  61. [Rust] Android 团队宣布 Android 开源项目(AOSP),已支持 Rust 语言来开发 Android 系统本身
  62. [Rust] RustyHermit——基于 Rust 实现的下一代容器 Unikernel
  63. [Rust] Rustic:完善的纯粹 Rust 技术栈实现的国际象棋引擎,多平台支持(甚至包括嵌入式设备树莓派 Raspberry Pi、Buster)
  64. [Rust] Rust 迭代器(Iterator trait )的要诀和技巧
  65. [Rust] 使用 Rust 极致提升 Python 性能:图表和绘图提升 24 倍,数据计算提升 10 倍
  66. [Rust] 【2021-04-03】Rust 核心团队人员变动
  67. [Rust] Rust web 框架现状【2021 年 1 季度】
  68. [Rust] Rust 官方周报 384 期(2021-03-31)
  69. [Rust] Rust 中的解析器组合因子(parser combinators)
  70. [生活] 毕马威(KPMG)调查报告:人工智能的实际采用,在新冠疫情(COVID-19)期间大幅提升
  71. [Python] HPy - 为 Python 扩展提供更优秀的 C API
  72. [Rust] 2021 年,学习 Rust 的网络资源推荐(2)
  73. [Rust] 2021 年,学习 Rust 的网络资源推荐
  74. [生活] 况属高风晚,山山黄叶飞——彭州葛仙山露营随笔
  75. [Rust] Rust 1.51.0 已正式发布,及其新特性详述
  76. [Rust] 为 Async Rust 构建共享的愿景文档—— Rust 社区的讲“故事”,可获奖
  77. [Rust] Rust 纪元第 382 周最佳 crate:ibig 的实践,以及和 num crate 的比较
  78. [Rust] Rust 1.51.0 稳定版本改进介绍
  79. [Rust] Rust 中将 markdown 渲染为 html
  80. [生活] 国民应用 App 的用户隐私数据窥探
  81. [GraphQL] 构建 Rust 异步 GraphQL 服务:基于 tide + async-graphql + mongodb(3)- 重构
  82. [GraphQL] 构建 Rust 异步 GraphQL 服务:基于 tide + async-graphql + mongodb(2)- 查询服务
  83. [GraphQL] 构建 Rust 异步 GraphQL 服务:基于 tide + async-graphql + mongodb(1)- 起步及 crate 选择
  84. [Rust] Rust 操控大疆可编程 tello 无人机

Topics

rust(84)

graphql(17)

rust-官方周报(17)

webassembly(16)

wasm(10)

tide(9)

async-graphql(9)

yew(9)

rust-web(8)

rust-官方博客(8)

this-week-in-rust(6)

mysql(5)

actix-web(5)

rbatis(5)

android(4)

mongodb(3)

json-web-token(3)

jwt(3)

cargo(3)

技术延伸(3)

rust-wasm(3)

trunk(3)

handlebars(3)

rhai(3)

async-std(3)

用户隐私(2)

学习资料(2)

python(2)

ai(2)

人工智能(2)

postgresql(2)

rust-compiler(2)

rust-基金会(2)

rust-foundation(2)

rustup(2)

rust-toolchain(2)

rust-工具链(2)

rust-游戏开发(2)

rust-区块链(2)

rust-2021(2)

graphql-client(2)

surf(2)

rust-game(2)

rusthub(2)

tello(1)

drone(1)

无人机(1)

隐私数据(1)

markdown(1)

html(1)

crate(1)

async(1)

异步(1)

旅游(1)

不忘生活(1)

葛仙山(1)

hpy(1)

python-扩展(1)

正则表达式(1)

解析器组合因子(1)

组合器(1)

regular-expression(1)

parser-combinator(1)

regex(1)

官方更新(1)

rust-工作招聘(1)

rust-技术资料(1)

rust-周最佳-crate(1)

rust-web-框架(1)

rust-web-framework(1)

rust-核心团队(1)

rust-core-team(1)

rust-language-team(1)

pyo3(1)

rust-python-集成(1)

python-性能改进(1)

迭代器(1)

iterator-trait(1)

国际象棋(1)

chess(1)

游戏引擎(1)

game-engine(1)

虚拟化(1)

unikernel(1)

rustyhermit(1)

linux(1)

virtualization(1)

sandboxing(1)

沙箱技术(1)

数据采集(1)

异步数据采集(1)

docker(1)

镜像(1)

生产环境(1)

rust-评价(1)

rust-2021-edition(1)

rust-2021-版本(1)

graphql-查询(1)

vision-doc(1)

愿景文档(1)

代码重构(1)

steering-cycle(1)

方向周期(1)

隐私声明(1)

机器人(1)

robotics(1)

rustdoc(1)

rust-编译器(1)

实时音频(1)

real-time-audio(1)

变更服务(1)

mutation(1)

查询服务(1)

query(1)

rust-贡献者(1)

rust-轶事(1)

rust-稳定版(1)

rust-预发布(1)

rust-测试(1)

安全编程(1)

可信计算(1)

安全代码(1)

secure-code(1)

rust-android-integrate(1)

rust-embedded(1)

rust-嵌入式(1)

rust-生产环境(1)

rust-production(1)

网页快照(1)

网页截图(1)

水印效果(1)

图片水印(1)

yew-router(1)

css(1)

web-前端(1)

wasm-bindgen(1)

区块链(1)

blockchain(1)

dotenv(1)

标识符(1)

rust-1.53.0(1)

rust-1.56.0(1)

rust-项目升级(1)

异步运行时(1)

ssr(1)

tokio(1)

warp(1)

reqwest(1)

graphql-rust(1)


Elsewhere

- Open Source
  1. github/zzy
  2. github/sansx
- Learning & Studying
  1. Rust 学习资料 - 泥芹