roadster 0.5.7

A "Batteries Included" web framework for rust designed to get you moving fast.
Documentation
# Roadster

[![crates.io](https://img.shields.io/crates/v/roadster.svg)](https://crates.io/crates/roadster)
[![docs.rs](https://img.shields.io/docsrs/roadster?logo=docsdotrs)](https://docs.rs/roadster/latest/roadster/)
[![Crates.io MSRV](https://img.shields.io/crates/msrv/roadster)](https://crates.io/crates/roadster)
[![Crates.io License](https://img.shields.io/crates/l/roadster)](https://crates.io/crates/roadster)
[![GitHub Discussions](https://img.shields.io/github/discussions/roadster-rs/roadster?logo=github)](https://github.com/roadster-rs/roadster/discussions)
[![codecov](https://codecov.io/gh/roadster-rs/roadster/graph/badge.svg?token=JIMN3U8K88)](https://codecov.io/gh/roadster-rs/roadster)
[![Checks](https://github.com/roadster-rs/roadster/actions/workflows/ci.yml/badge.svg)](https://github.com/roadster-rs/roadster/actions/workflows/ci.yml)
[![Feature Powerset](https://github.com/roadster-rs/roadster/actions/workflows/feature_powerset.yml/badge.svg)](https://github.com/roadster-rs/roadster/actions/workflows/feature_powerset.yml)
[![dependency status](https://deps.rs/crate/roadster/latest/status.svg)](https://deps.rs/crate/roadster/)

A "Batteries Included" web framework for rust designed to get you moving fast 🏎️. Inspired by other fully-featured
frameworks such
as [Rails](https://rubyonrails.org/), [Django](https://www.djangoproject.com/), [Laravel](https://laravel.com/), [Loco](https://github.com/loco-rs/loco),
and [Poem](https://github.com/poem-web/poem).

## Features

- Built on Tokio's web stack (axum, tower, hyper, tracing). App behavior can be easily extended by taking advantage of
  all the resources in the tokio ecosystem.
- Built-in support for HTTP APIs via [Axum]https://crates.io/crates/axum (with the `http` feature) and gRPC APIs
  via [Tonic]https://crates.io/crates/tonic (with the `grpc` feature).
- Auto-generates an OpenAPI schema for HTTP API routes defined with [aide]https://crates.io/crates/aide (requires
  the `open-api` feature).
- Support for running arbitrary long-running services (e.g., an API format not supported out of the box) with minimal
  boilerplate. Simply provide a
  [FunctionService]https://docs.rs/roadster/latest/roadster/service/function/service/struct.FunctionService.html
  with your async function and register it in the `App#services` method.
- Provides sensible defaults so you can focus on building your app, but most (all?) of the built-in behavior can be
  customized or disabled via per-environment configuration files.
- Uses `#![forbid(unsafe_code)]` to ensure all code in Roadster is 100% safe rust.
- Provides a CLI for common commands, and allows consumers to provide their own CLI commands
  using [clap]https://crates.io/crates/clap (requires the `cli` feature)
- Provides sample JWT extractor for Axum (requires the `jwt-ietf` and/or `jwt-openid` features). Also provides a general
  JWT extractor for Axum that simply puts all claims into a map (available with the `jwt` feature)
- Built-in support for [SeaORM]https://crates.io/crates/sea-orm, including creating DB connections (requires
  the `db-sql` feature)
- Built-in support for [Sidekiq.rs]https://crates.io/crates/rusty-sidekiq for running async/background jobs (requires
  the `sidekiq` feature)
- Structured logs/traces using tokio's [tracing]https://docs.rs/tracing/latest/tracing/ crate. Export traces/metrics
  using OpenTelemetry (requires the `otel` feature).
- Health checks to ensure the app's external dependencies are healthy

# Getting started

## Start local DB

```shell
# Replace `full_dev` with your app name, e.g., `myapp_dev` (unless you're using our `full` example, as demonstrated below)
# Dev
docker run -d -p 5432:5432 -e POSTGRES_USER=roadster -e POSTGRES_DB=full_dev -e POSTGRES_PASSWORD=roadster postgres:15.3-alpine
# Test
docker run -d -p 5433:5432 -e POSTGRES_USER=roadster -e POSTGRES_DB=full_test -e POSTGRES_PASSWORD=roadster postgres:15.3-alpine
```

## Start local Redis instance (for [Sidekiq.rs]https://crates.io/crates/rusty-sidekiq)

```shell
# Dev
docker run -d -p 6379:6379 redis:7.2-alpine
# Test
docker run -d -p 6380:6379 redis:7.2-alpine
```

## Create your app

```shell
# Todo: Add instructions for creating a new app
# Using one of our examples for now 
git clone https://github.com/roadster-rs/roadster.git
cd roadster/examples/full
```

## Set the environment (production/development/test)

```shell
# Either set it as an environment variable
export ROADSTER__ENVIRONMENT=development
# Or add it to a `.env` file
echo ROADSTER__ENVIRONMENT=development >> .env
```

## Start your app

```shell
cargo run
```

# Add a UI

Currently, Roadster is focused on back-end API development with Rust. We leave it to the consumer to decide how they
prefer to add a front-end, e.g., using an established JS/TS
framework ([React](https://react.dev/) / [Next](https://nextjs.org/) / [Vue](https://vuejs.org/) / [Svelte](https://svelte.dev/) / [Solid](https://www.solidjs.com/)
/ etc) or
using a Rust front-end
framework ([Leptos](https://github.com/leptos-rs/leptos) / [Yew](https://github.com/yewstack/yew) / [Perseus](https://github.com/framesurge/perseus/) / [Sycamore](https://github.com/sycamore-rs/sycamore)
/ etc). That said, we do have some examples of how to use Roadster with some these frameworks.

## Examples

| Framework                                     | Example                                                                             |
|-----------------------------------------------|-------------------------------------------------------------------------------------|
| [Leptos]https://github.com/leptos-rs/leptos | [leptos-ssr]https://github.com/roadster-rs/roadster/tree/main/examples/leptos-ssr |

# Tracing + OpenTelemetry

Roadster allows reporting traces and metrics using the `tracing` and `opentelemetry_rust` integrations. Provide the URL
of your OTLP exporter in order to report the trace/metric data to your telemetry provider (e.g., SigNoz, New Relic,
Datadog, etc).

## View traces locally

You can also view traces locally using, for example, Jaeger or SigNoz.

### Jaeger

The easiest way to view OpenTelemetry Traces locally is by
running [Jaeger](https://www.jaegertracing.io/docs/1.54/getting-started/).

1. Set `ROADSTER__TRACING__OTLP_ENDPOINT="http://localhost:4317"` in your `.env` file, or in
   your `config/development.toml` or `config/test.toml` configs as appropriate.
2. Run the following command:
    ```shell
    docker run --rm --name jaeger \
        -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
        -p 6831:6831/udp \
        -p 6832:6832/udp \
        -p 5778:5778 \
        -p 16686:16686 \
        -p 4317:4317 \
        -p 4318:4318 \
        -p 14250:14250 \
        -p 14268:14268 \
        -p 14269:14269 \
        -p 9411:9411 \
        jaegertracing/all-in-one:1.53
    ```
3. Navigate to the UI, which is available at [localhost:16686]http://localhost:16686.

### Signoz

Another option to view traces (and metrics) locally is to run [Signoz](https://signoz.io/docs/install/docker/).

1. Set `ROADSTER__TRACING__OTLP_ENDPOINT="http://localhost:4317"` in your `.env` file, or in
   your `config/development.toml` or `config/test.toml` configs as appropriate.
2. Install and run Signoz in a directory of your choice
   ```shell
   # Clone the repo
   git clone -b main https://github.com/SigNoz/signoz.git && cd signoz/deploy/
   # Remove the sample application: https://signoz.io/docs/operate/docker-standalone/#remove-the-sample-application-from-signoz-dashboard
   vim docker/clickhouse-setup/docker-compose.yaml
   # Remove the `services.hotrod` and `services.load-hotrod` sections, then exit `vim`
   # Run the `docker compose` command
   ./install.sh
   ```
3. Navigate to the UI, which is available at [localhost:3301]http://localhost:3301.
4. To stop Signoz, run the following:
   ```shell
   docker compose -f docker/clickhouse-setup/docker-compose.yaml stop
   ```

# Background/async job queue using [Sidekiq.rs]https://crates.io/crates/rusty-sidekiq

This crate is a rust implementation of [Sidekiq](https://sidekiq.org/), which is usually used with Ruby on Rails. All we
need in order to use this is a Redis instance.

## Sidekiq dashboard

We provide a [sample repo](https://github.com/roadster-rs/standalone_sidekiq_dashboard) to run the sidekiq dashboard
locally in a standalone docker container.

```shell
git clone https://github.com/roadster-rs/standalone_sidekiq_dashboard.git
cd standalone_sidekiq_dashboard
docker build -t standalone-sidekiq .
# Linux docker commands
# Development
docker run -d --network=host standalone-sidekiq
# Test
docker run -d --network=host -e REDIS_URL='redis://localhost:6380' standalone-sidekiq

# Mac docker commands -- todo: see if there's a command that will work on both mac and linux
# Development
docker run -d -p 9292:9292 -e REDIS_URL=redis://host.docker.internal:6379 standalone-sidekiq
# Test
docker run -d -p 9292:9292 -e REDIS_URL=redis://host.docker.internal:6380 standalone-sidekiq
```

## Redis Insights

You can also inspect the Redis DB directly using [RedisInsight](https://redis.io/docs/connect/insight/).

```shell
# Linux docker commands
docker run -d --name redisinsight --network=host -p 5540:5540 redis/redisinsight:latest
# Mac docker commands -- todo: see if there's a command that will work on both mac and linux
# Use `host.docker.internal` as the host domain in redis insight (instead of `127.0.0.1`)
docker run -d --name redisinsight -p 5540:5540 redis/redisinsight:latest
```