Skip to content

Commit

Permalink
Merge branch 'master' into docs/clarify-options
Browse files Browse the repository at this point in the history
  • Loading branch information
kaplanelad authored Oct 13, 2024
2 parents 85351f8 + e544fa4 commit 74b684e
Show file tree
Hide file tree
Showing 62 changed files with 1,404 additions and 567 deletions.
69 changes: 69 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,76 @@
* `Format(respond_to): Format` extractor in controller can now be replaced with `respond_to: RespondTo` extractor for less typing.
* When supplying data to views, you can now use `data!` instead of `serde_json::json!` for shorthand.
* Refactor middlewares. [https://github.com/loco-rs/loco/pull/785](https://github.com/loco-rs/loco/pull/785)
* **NEW (BREAKING)** background worker subsystem is now queue agnostic. Providing for both Redis and Postgres with a change of configuration. This means you can now use a full-Postgres stack to remove Redis as a dependency if you wish. Here are steps to migrate your codebase:

```rust
// in your app.rs, change the worker registration code:

// BEFORE
fn connect_workers<'a>(p: &'a mut Processor, ctx: &'a AppContext) {
p.register(DownloadWorker::build(ctx));
}

// AFTER
async fn connect_workers(ctx: &AppContext, queue: &Queue) -> Result<()>{
queue.register(DownloadWorker::build(ctx)).await?;
Ok(())
}

// in your app.rs, remove the `worker` module references.
// REMOVE
worker::{AppWorker, Processor},

// in your workers change the signature, and add the `build` function

// BEFORE
impl worker::Worker<DownloadWorkerArgs> for DownloadWorker {
async fn perform(&self, args: DownloadWorkerArgs) -> worker::Result<()> {

// AFTER
#[async_trait]
impl BackgroundWorker<DownloadWorkerArgs> for DownloadWorker {
fn build(ctx: &AppContext) -> Self {
Self { ctx: ctx.clone() }
}
async fn perform(&self, args: DownloadWorkerArgs) -> Result<()> {

// Finally, remove the `AppWorker` trait implementation completely.

// REMOVE
impl worker::AppWorker<DownloadWorkerArgs> for DownloadWorker {
fn build(ctx: &AppContext) -> Self {
Self { ctx: ctx.clone() }
}
}
```

* **UPGRADED (BREAKING)**: `validator` crate was upgraded which require some small tweaks to work with the new API:

```rust
// BEFORE:
#[validate(custom = "validation::is_valid_email")]
pub email: String,

// AFTER:
#[validate(custom (function = "validation::is_valid_email"))]
pub email: String,
```

Then update your `Cargo.toml` to take version `0.18`:

```toml
# update
validator = { version = "0.18" }
```

* **UPGRADED (BREAKING)**: `axum-test` crate was upgraded
Update your `Cargo.toml` to version `16`:

```toml
# update
axum-test = { version = "16" }
```

## v0.9.0

Expand Down
29 changes: 19 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = ["auth_jwt", "cli", "with-db", "cache_inmem"]
default = ["auth_jwt", "cli", "with-db", "cache_inmem", "bg_redis", "bg_pg"]
auth_jwt = ["dep:jsonwebtoken"]
cli = ["dep:clap"]
testing = ["dep:axum-test"]
Expand All @@ -35,6 +35,8 @@ storage_azure = ["object_store/azure"]
storage_gcp = ["object_store/gcp"]
# Cache feature
cache_inmem = ["dep:moka"]
bg_redis = ["dep:rusty-sidekiq", "dep:bb8"]
bg_pg = ["dep:sqlx", "dep:ulid"]

[dependencies]
backtrace_printer = { version = "1.3.0" }
Expand All @@ -59,10 +61,8 @@ serde_json = "1"
serde_yaml = "0.9"
serde_variant = "0.1.2"

# worker fwk
rusty-sidekiq = { version = "0.8.2", default-features = false }

async-trait = { workspace = true }
bb8 = "0.8.1"

axum = { workspace = true }
axum-extra = { version = "0.9", features = ["cookie"] }
Expand Down Expand Up @@ -92,34 +92,33 @@ byte-unit = "4.0.19"

argon2 = { version = "0.5.2", features = ["std"] }
rand = { version = "0.8.5", features = ["std"] }
jsonwebtoken = { version = "9.1.0", optional = true }
bcrypt = { version = "0.15.0", optional = true }
validator = { version = "0.16.1", features = ["derive"] }
jsonwebtoken = { version = "9.3.0", optional = true }
validator = { version = "0.18.1", features = ["derive"] }
futures-util = "0.3"
tower = { workspace = true }
hyper = "1.1"
mime = "0.3"
bytes = "1.1"
ipnetwork = "0.20.0"

axum-test = { version = "14.3.0", optional = true }
axum-test = { version = "16.1.0", optional = true }

# gen
rrgen = "0.5.3"
chrono = "0.4.31"
cargo_metadata = "0.18.1"
dialoguer = "0.11.0"

cfg-if = "1"

uuid = { version = "1.10.0", features = ["v4", "fast-rng"] }
requestty = "0.5.0"

# A socket.io server implementation
socketioxide = { version = "0.14.0", features = ["state"], optional = true }


# File Upload
object_store = { version = "0.10.2", default-features = false }
object_store = { version = "0.11.0", default-features = false }

# cache
moka = { version = "0.12.7", features = ["sync"], optional = true }
Expand All @@ -128,6 +127,16 @@ moka = { version = "0.12.7", features = ["sync"], optional = true }
tokio-cron-scheduler = { version = "0.11.0", features = ["signal"] }
english-to-cron = { version = "0.1.2" }

# bg_pg: postgres workers
sqlx = { version = "0.7", default-features = false, features = [
"postgres",
], optional = true }
ulid = { version = "1", optional = true }

# bg_redis: redis workers
rusty-sidekiq = { version = "0.8.2", default-features = false, optional = true }
bb8 = { version = "0.8.1", optional = true }

[workspace.dependencies]
async-trait = { version = "0.1.74" }
axum = { version = "0.7.5", features = ["macros"] }
Expand Down
2 changes: 1 addition & 1 deletion README.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Vous pouvez maintenant créer votre nouvelle application (choisissez "`SaaS` app
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · SaaS app (with DB and user auth)
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokyo async tasks)
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)
✔ ❯ Select an asset serving configuration · Client (configures assets for frontend serving)

🚂 Loco app generated successfully in:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Now you can create your new app (choose "`SaaS` app").
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · SaaS app (with DB and user auth)
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokyo async tasks)
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)
✔ ❯ Select an asset serving configuration · Client (configures assets for frontend serving)

🚂 Loco app generated successfully in:
Expand Down
4 changes: 2 additions & 2 deletions docs-site/content/blog/axum-session.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Hooks for App {
Now, you can create your controller that uses Axum session. Use the `cargo loco generate controller` command:

```sh
❯ cargo loco generate controller mysession
❯ cargo loco generate controller mysession -k api
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
Running `target/debug/axum-session-cli generate controller mysession`
added: "src/controllers/mysession.rs"
Expand Down Expand Up @@ -166,7 +166,7 @@ impl Hooks for App {
Create the controller as before using `cargo loco generate controller`

```sh
❯ cargo loco generate controller mysession
❯ cargo loco generate controller mysession -k api
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
Running `target/debug/axum-session-cli generate controller mysession`
added: "src/controllers/mysession.rs"
Expand Down
14 changes: 7 additions & 7 deletions docs-site/content/docs/getting-started/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Now you can create your new app (choose "SaaS app" for built-in authentication).
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · SaaS app (with DB and user auth)
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokyo async tasks)
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)
✔ ❯ Select an asset serving configuration · Client (configures assets for frontend serving)

🚂 Loco app generated successfully in:
Expand Down Expand Up @@ -139,7 +139,7 @@ The built in <code>_health</code> route will tell you that you have configured y
Let's add a quick _hello_ response to our service.

```sh
$ cargo loco generate controller guide
$ cargo loco generate controller guide -k api
added: "src/controllers/guide.rs"
injected: "src/controllers/mod.rs"
injected: "src/app.rs"
Expand Down Expand Up @@ -307,7 +307,7 @@ src/
mod.rs
```

**This is an important _cognitive_ principle**. And the principle claims that you can only create safe, compatible API responses if you treat those as a separate, independently goverened _thing_ -- hence the 'V' in MVC, in Loco.
**This is an important _cognitive_ principle**. And the principle claims that you can only create safe, compatible API responses if you treat those as a separate, independently governed _thing_ -- hence the 'V' in MVC, in Loco.

<div class="infobox">
Models in Loco carry the same semantics as in Rails: <b>fat models, slim controllers</b>. This means that every time you want to build something -- <em>you reach out to a model</em>.
Expand Down Expand Up @@ -465,7 +465,7 @@ $ cargo playground
We're now ready to plug this into an `articles` controller. First, generate a new controller:
```sh
$ cargo loco generate controller articles
$ cargo loco generate controller articles -k api
added: "src/controllers/articles.rs"
injected: "src/controllers/mod.rs"
injected: "src/app.rs"
Expand Down Expand Up @@ -630,7 +630,7 @@ Let's add another model, this time: `Comment`. We want to create a relation - a
Instead of coding the model and controller by hand, we're going to create a **comment scaffold** which will generate a fully working CRUD API comments. We're also going to use the special `references` type:
```sh
$ cargo loco generate scaffold comment content:text article:references
$ cargo loco generate scaffold comment content:text article:references -k api
```
If you peek into the new migration, you'll discover a new database relation in the articles table:
Expand Down Expand Up @@ -802,7 +802,7 @@ impl Task for UserReport {
// variables through the CLI:
// `$ cargo loco task name:foobar count:2`
// will appear as {"name":"foobar", "count":2} in `vars`
async fn run(&self, app_context: &AppContext, vars: &BTreeMap<String, String>) -> Result<()> {
async fn run(&self, app_context: &AppContext, vars: &Vars) -> Result<()> {
let users = users::Entity::find().all(&app_context.db).await?;
println!("args: {vars:?}");
println!("!!! user_report: listing users !!!");
Expand All @@ -829,7 +829,7 @@ args: Vars { cli: {"var1": "val1", "var2": "val2"} }
------------------------
done: 0 users
```
If you have not added an user before, the report will be empty.
If you have not added an user before, the report will be empty.
To add an user check out chapter [Registering a New User](/docs/getting-started/tour/#registering-a-new-user) of [A Quick Tour with Loco](/docs/getting-started/tour/).
Expand Down
2 changes: 1 addition & 1 deletion docs-site/content/docs/getting-started/starters.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Create a starter:
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · SaaS app (with DB and user auth)
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokyo async tasks)
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)
✔ ❯ Select an asset serving configuration · Client (configures assets for frontend serving)

🚂 Loco app generated successfully in:
Expand Down
6 changes: 3 additions & 3 deletions docs-site/content/docs/getting-started/tour/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ cargo install sea-orm-cli # Only when DB is needed
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · SaaS app (with DB and user auth)
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokyo async tasks)
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)
✔ ❯ Select an asset serving configuration · Client (configures assets for frontend serving)

🚂 Loco app generated successfully in:
Expand Down Expand Up @@ -106,7 +106,7 @@ listening on port 5150
We have a base SaaS app with user authentication generated for us. Let's make it a blog backend by adding a `post` and a full CRUD API using `scaffold`:

```sh
$ cargo loco generate scaffold post title:string content:text
$ cargo loco generate scaffold post title:string content:text -k api

:
:
Expand Down Expand Up @@ -168,7 +168,7 @@ For those counting -- the commands for creating a blog backend were:
1. `cargo install loco-cli`
2. `cargo install sea-orm-cli`
3. `loco new`
4. `cargo loco generate scaffold post title:string content:text`
4. `cargo loco generate scaffold post title:string content:text -k api`

Done! enjoy your ride with `loco` 🚂

Expand Down
32 changes: 32 additions & 0 deletions docs-site/content/docs/processing/mailers.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,38 @@ impl Mailer for AuthMailer {
}
```

### Using a mail catcher in development

You can use an app like `MailHog` or `mailtutan` (written in Rust):

```
$ cargo install mailtutan
$ mailtutan
listening on smtp://0.0.0.0:1025
listening on http://0.0.0.0:1080
```

This will bring up a local smtp server and a nice UI on `http://localhost:1080` that "catches" and shows emails as they are received.

And then put this in your `development.yaml`:

```yaml
# Mailer Configuration.
mailer:
# SMTP mailer configuration.
smtp:
# Enable/Disable smtp mailer.
enable: true
# SMTP server host. e.x localhost, smtp.gmail.com
host: localhost
# SMTP server port
port: 1025
# Use secure connection (SSL/TLS).
secure: false
```

Now your mailer workers will send email to the SMTP server at `localhost`.

## Adding a mailer

You can generate a mailer:
Expand Down
Loading

0 comments on commit 74b684e

Please sign in to comment.