Update zino-core

This commit is contained in:
photino 2023-01-07 18:32:12 +08:00
parent f9f4c5f3e9
commit e776372d43
16 changed files with 105 additions and 93 deletions

View File

@ -1,2 +1 @@
# zino
A minimal web framework.
zino/README.md

View File

@ -1,6 +1,6 @@
[package]
name = "axum-app"
version = "0.2.2"
version = "0.2.3"
rust-version = "1.68"
edition = "2021"
publish = false

View File

@ -28,7 +28,7 @@ pub(super) fn every_30s(job_id: Uuid, job_data: &mut Map) -> BoxFuture {
.unwrap_or_default();
job_data.insert("current".to_string(), DateTime::now().to_string().into());
job_data.insert("counter".to_string(), counter.into());
println!("job {job_id} is executed every 45 seconds: {job_data:?}");
println!("async job {job_id} is executed every 30 seconds: {job_data:?}");
Box::pin(async {
let query = Query::new();

View File

@ -1,7 +1,7 @@
[package]
name = "zino-core"
description = "Core types and traits for zino."
version = "0.2.2"
version = "0.2.3"
rust-version = "1.68"
edition = "2021"
license = "MIT"

View File

@ -15,7 +15,7 @@ pub trait Application {
/// Registers routes.
fn register(self, routes: HashMap<&'static str, Self::Router>) -> Self;
/// Spawns a new thread to run jobs.
/// Spawns a new thread to run cron jobs.
fn spawn(self, jobs: HashMap<&'static str, CronJob>) -> Self
where
Self: Sized,

View File

@ -96,12 +96,10 @@ impl Mutation {
"$append" => {
if let Some(update) = value.as_object() {
for (key, value) in update.iter() {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {key} || {value}");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {key} || {value}");
mutations.push(mutation);
}
}
}
@ -109,12 +107,10 @@ impl Mutation {
"$preppend" => {
if let Some(update) = value.as_object() {
for (key, value) in update.iter() {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {value} || {key}");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {value} || {key}");
mutations.push(mutation);
}
}
}
@ -122,12 +118,10 @@ impl Mutation {
"$pull" => {
if let Some(update) = value.as_object() {
for (key, value) in update.iter() {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = array_remove({key}, {value})");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = array_remove({key}, {value})");
mutations.push(mutation);
}
}
}
@ -135,12 +129,10 @@ impl Mutation {
"$inc" => {
if let Some(update) = value.as_object() {
for (key, value) in update.iter() {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {key} + {value}");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {key} + {value}");
mutations.push(mutation);
}
}
}
@ -148,12 +140,10 @@ impl Mutation {
"$mul" => {
if let Some(update) = value.as_object() {
for (key, value) in update.iter() {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {key} * {value}");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {key} * {value}");
mutations.push(mutation);
}
}
}
@ -161,12 +151,10 @@ impl Mutation {
"$min" => {
if let Some(update) = value.as_object() {
for (key, value) in update.iter() {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = LEAST({key}, {value})");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = LEAST({key}, {value})");
mutations.push(mutation);
}
}
}
@ -174,23 +162,19 @@ impl Mutation {
"$max" => {
if let Some(update) = value.as_object() {
for (key, value) in update.iter() {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = GREATEST({key}, {value})");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = GREATEST({key}, {value})");
mutations.push(mutation);
}
}
}
}
_ => {
if fields.contains(key) {
if let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {value}");
mutations.push(mutation);
}
if fields.contains(key) && let Some(col) = M::get_column(key) {
let value = col.encode_postgres_value(value);
let mutation = format!("{key} = {value}");
mutations.push(mutation);
}
}
}

View File

@ -407,8 +407,8 @@ pub trait Schema: 'static + Send + Sync + Model {
}
}
/// Fetches the associated data for `Vec<Map>` using a merged select on the primary key,
/// which solves the `N+1` problem.
/// Fetches the associated data in the corresponding `columns` for `Vec<Map>` using
/// a merged select on the primary key, which solves the `N+1` problem.
async fn fetch(
mut query: Query,
data: &mut Vec<Map>,
@ -483,8 +483,8 @@ pub trait Schema: 'static + Send + Sync + Model {
u64::try_from(associations.len()).map_err(|err| Error::Decode(Box::new(err)))
}
/// Fetches the associated data for `Map` using a merged select on the primary key,
/// which solves the `N+1` problem.
/// Fetches the associated data in the corresponding `columns` for `Map` using
/// a merged select on the primary key, which solves the `N+1` problem.
async fn fetch_one(mut query: Query, data: &mut Map, columns: &[String]) -> Result<u64, Error> {
let pool = Self::init_reader().await.ok_or(Error::PoolClosed)?.pool();
let table_name = Self::table_name();

View File

@ -1,7 +1,10 @@
//! Core types and traits for zino.
//! Core types and traits for [`zino`].
//!
//! [`zino`]: https://github.com/photino/zino
#![feature(async_fn_in_trait)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(once_cell)]
#![feature(string_leak)]
#![feature(type_alias_impl_trait)]

View File

@ -1,7 +1,7 @@
[package]
name = "zino-derive"
description = "Derived traits for zino."
version = "0.2.2"
version = "0.2.3"
rust-version = "1.68"
edition = "2021"
license = "MIT"
@ -20,4 +20,4 @@ syn = { version = "1.0.107", features = ["full", "extra-traits"] }
[dependencies.zino-core]
path = "../zino-core"
version = "0.2.2"
version = "0.2.3"

View File

@ -1,4 +1,6 @@
//! Derived traits for zino.
//! Derived traits for [`zino`].
//!
//! [`zino`]: https://github.com/photino/zino
#![feature(let_chains)]
#![forbid(unsafe_code)]

View File

@ -1,7 +1,7 @@
[package]
name = "zino-model"
description = "Model types for zino."
version = "0.2.2"
version = "0.2.3"
rust-version = "1.68"
edition = "2021"
license = "MIT"
@ -15,8 +15,8 @@ serde = { version = "1.0.152", features = ["derive"] }
[dependencies.zino-core]
path = "../zino-core"
version = "0.2.2"
version = "0.2.3"
[dependencies.zino-derive]
path = "../zino-derive"
version = "0.2.2"
version = "0.2.3"

View File

@ -1,4 +1,6 @@
//! Model types for zino.
//! Model types for [`zino`].
//!
//! [`zino`]: https://github.com/photino/zino
#![feature(async_fn_in_trait)]
#![feature(once_cell)]

View File

@ -1,7 +1,7 @@
[package]
name = "zino"
description = "A minimal web framework."
version = "0.2.2"
version = "0.2.3"
rust-version = "1.68"
edition = "2021"
license = "MIT"
@ -36,4 +36,4 @@ tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json", "lo
[dependencies.zino-core]
path = "../zino-core"
version = "0.2.2"
version = "0.2.3"

View File

@ -1,40 +1,45 @@
# zino
`zino` is a full featured web application framework that focuses on productivity and performance.
`zino` is a full featured web application framework which focuses on productivity and performance.
[![Crates.io](https://img.shields.io/crates/v/zino)][zino]
[![Documentation](https://docs.rs/zino/badge.svg)][zino-docs]
## Highlights
## High level features
- ✨ Full features for web development out of the box.
- 💖 Minimal design, modular architecture and ease to use.
- 🚀 Embrace practical conventions to get high performance.
- 🐘 Built-in ORM for PostgreSQL based on [`sqlx`][sqlx].
- 📈 Support for `tracing`, `logging` and `metrics`.
- 🚀 Out-of-the-box features for rapid application development.
- ✨ Minimal design, modular architecture and high-level abstractions.
- ⚡ Embrace practical conventions to get the best performance.
- 🐘 Highly optimized ORM for PostgreSQL built with [`sqlx`][sqlx].
- ⏲ Lightweight scheduler for sync and async cron jobs.
- 📊 Support for `tracing`, `logging` and `metrics`.
## Getting started
You can start with the example [`axum-app`][axum-app].
You can start with the example [`axum-app`].
## Documentation
## Crates
`zino` consists of 4 crates:
- [zino][zino-docs]: Named features.
- [zino-core][zino-core-docs]: Core types and traits.
- [zino-derive][zino-derive-docs]: Derived traits.
- [zino-model][zino-model-docs]: Model types.
| Name | Description | Crates.io | Documentation |
|-----------------|------------------------|--------------|---------------|
| [`zino`] | Named features. | [![crates.io](https://img.shields.io/crates/v/zino)][zino] | [![Documentation](https://docs.rs/zino/badge.svg)][zino-docs] |
| [`zino-core`] | Core types and traits. | [![crates.io](https://img.shields.io/crates/v/zino-core)][zino-core] | [![Documentation](https://docs.rs/zino-core/badge.svg)][zino-core-docs] |
| [`zino-derive`] | Derived traits. | [![crates.io](https://img.shields.io/crates/v/zino-derive)][zino-derive] | [![Documentation](https://docs.rs/zino-derive/badge.svg)][zino-derive-docs] |
| [`zino-model`] | Model types. | [![crates.io](https://img.shields.io/crates/v/zino-model)][zino-model] | [![Documentation](https://docs.rs/zino-model/badge.svg)][zino-model-docs] |
## License
This project is licensed under the [MIT license][license].
[`zino`]: https://github.com/photino/zino/tree/main/zino
[`zino-core`]: https://github.com/photino/zino/tree/main/zino-core
[`zino-derive`]: https://github.com/photino/zino/tree/main/zino-derive
[`zino-model`]: https://github.com/photino/zino/tree/main/zino-model
[zino]: https://crates.io/crates/zino
[sqlx]: https://crates.io/crates/sqlx
[axum-app]: https://github.com/photino/zino/tree/main/examples/axum-app
[zino-docs]: https://docs.rs/zino
[zino-core]: https://crates.io/crates/zino-core
[zino-core-docs]: https://docs.rs/zino-core
[zino-derive]: https://crates.io/crates/zino-derive
[zino-derive-docs]: https://docs.rs/zino-derive
[zino-model]: https://crates.io/crates/zino-model
[zino-model-docs]: https://docs.rs/zino-model
[sqlx]: https://crates.io/crates/sqlx
[`axum-app`]: https://github.com/photino/zino/tree/main/examples/axum-app
[license]: https://github.com/photino/zino/blob/main/LICENSE

View File

@ -13,7 +13,6 @@ use std::{
net::SocketAddr,
path::Path,
sync::{Arc, LazyLock},
thread,
time::{Duration, Instant},
};
use tokio::runtime::Builder;
@ -62,16 +61,17 @@ impl Application for AxumCluster {
/// Runs the application.
fn run(self, async_jobs: HashMap<&'static str, AsyncCronJob>) -> io::Result<()> {
let runtime = Builder::new_multi_thread().enable_all().build()?;
let mut scheduler = JobScheduler::new();
for (cron_expr, exec) in async_jobs {
scheduler.add(Job::new_async(cron_expr, exec));
}
let runtime = Builder::new_multi_thread().enable_all().build()?;
runtime.spawn(async move {
loop {
scheduler.tick_async().await;
thread::sleep(scheduler.time_till_next_job());
// Cannot use `std::thread::sleep` because it blocks the Tokio runtime.
tokio::time::sleep(scheduler.time_till_next_job()).await;
}
});

View File

@ -1,4 +1,21 @@
//! A minimal web framework.
//! [`zino`] is a full featured web application framework which focuses on productivity and performance.
//!
//! ## Highlights
//!
//! - 🚀 Out-of-the-box features for rapid application development.
//! - ✨ Minimal design, modular architecture and high-level abstractions.
//! - ⚡ Embrace practical conventions to get the best performance.
//! - 🐘 Highly optimized ORM for PostgreSQL built with [`sqlx`].
//! - ⏲ Lightweight scheduler for sync and async cron jobs.
//! - 📊 Support for `tracing`, `logging` and `metrics`.
//!
//! ## Getting started
//!
//! You can start with the example [`axum-app`].
//!
//! [`zino`]: https://github.com/photino/zino
//! [`sqlx`]: https://crates.io/crates/sqlx
//! [`axum-app`]: https://github.com/photino/zino/tree/main/examples/axum-app
#![feature(async_fn_in_trait)]
#![feature(once_cell)]