fix: redis connect (#2)

* fix: redis connect

* chore: add Readme and support no tls

* chore: cache docker build

* chore: update

* fix: fix postgres and redis connection

* chore: update port

* ci: lint
This commit is contained in:
Nathan.fooo 2023-05-05 00:00:02 +08:00 committed by GitHub
parent 920e7f9564
commit bb80fd5350
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 507 additions and 294 deletions

14
.cargo/config.toml Normal file
View File

@ -0,0 +1,14 @@
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "linker=clang", "-C", "link-arg=-fuse-ld=lld"]
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
[target.x86_64-pc-windows-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
[target.x86_64-apple-darwin]
rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/zld"]
[target.aarch64-apple-darwin]
rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/zld"]

9
.dockerignore Normal file
View File

@ -0,0 +1,9 @@
.env
.dockerignore
spec.yaml
target/
deploy/
tests/
Dockerfile
scripts/
migrations/

2
.env
View File

@ -1 +1 @@
DATABASE_URL="postgres://postgres:password@localhost:5432/appflowy_pg"
DATABASE_URL="postgres://postgres:password@localhost:5432/appflowy"

592
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,20 @@
FROM rust:1.56.1 as builder
FROM lukemathwalker/cargo-chef:latest-rust-1.65.0 as chef
WORKDIR /app
RUN apt update && apt install lld clang -y
FROM chef as planner
COPY . .
# Compute a lock-like file for our project
RUN cargo chef prepare --recipe-path recipe.json
FROM chef as builder
COPY --from=planner /app/recipe.json recipe.json
# Build our project dependencies
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
WORKDIR /app/services/appflowy_server
ENV SQLX_OFFLINE true
RUN RUSTFLAGS="-C opt-level=2" cargo build --release --bin appflowy_server
# Size optimization
#RUN strip ./target/release/appflowy_server
# Build the project
RUN cargo build --release --bin appflowy_server
FROM debian:bullseye-slim AS runtime
WORKDIR /app
@ -17,7 +25,8 @@ RUN apt-get update -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/services/target/release/appflowy_server /usr/local/bin/appflowy_server
COPY --from=builder /app/services/appflowy_server/configuration configuration
COPY --from=builder /app/target/release/appflowy_server /usr/local/bin/appflowy_server
COPY --from=builder /app/configuration configuration
ENV APP_ENVIRONMENT production
ENV RUST_BACKTRACE 1
CMD ["appflowy_server"]

View File

@ -1,21 +1,15 @@
ROOT = "./build"
SEMVER_VERSION=$(shell grep version Cargo.toml | awk -F"\"" '{print $$2}' | head -n 1)
.PHONY: init_database docker_image local_server docker_test
.PHONY: prerequisite local_test
init_database:
prerequisite:
POSTGRES_PORT=5432 ${ROOT}/init_database.sh
${ROOT}/init_redis.sh
docker_image:
source $(ROOT)/docker_env.sh && docker-compose up -d postgres_db
appflowy_server_image:
source $(ROOT)/docker_env.sh && docker-compose up -d appflowy_server
local_server:
cargo run
docker_test:
sh $(ROOT)/docker_test.sh
local_test:
# 🔥 Must run init_database first
SQLX_OFFLINE=true cargo test

67
README.md Normal file
View File

@ -0,0 +1,67 @@
## Pre-requisites
You'll need to install:
- [Rust](https://www.rust-lang.org/tools/install)
- [Docker](https://docs.docker.com/get-docker/)
Here are the Os-specific requirements:
### Windows
```bash
cargo install -f cargo-binutils
rustup component add llvm-tools-preview
```
```
cargo install --version="~0.6" sqlx-cli --no-default-features --features rustls,postgres
```
### Linux
```bash
# Ubuntu
sudo apt-get install lld clang libssl-dev postgresql-client
# Arch
sudo pacman -S lld clang postgresql
```
```
cargo install --version="~0.6" sqlx-cli --no-default-features --features rustls,postgres
```
### MacOS
```bash
brew install michaeleisel/zld/zld
```
```
cargo install --version="~0.6" sqlx-cli --no-default-features --features rustls,postgres
```
## How to build
Run `the init_db.sh` to create a Postgres database container in Docker:
```bash
./scripts/init_db.sh
```
Run the `init_redis.sh` to create a Redis container in Docker:
```bash
./scripts/init_redis.sh
```
Build the project:
```bash
cargo build
```
or you can try to run the tests in your local machine:
```bash
cargo test
```

View File

@ -4,7 +4,7 @@ export BACKEND_VERSION="v0.0.1"
export POSTGRES_USER=postgres
export POSTGRES_PASSWORD=password
export POSTGRES_PORT=5432
export POSTGRES_HOST=db
export POSTGRES_DB=appflowy_pg
export POSTGRES_HOST=postgres
export POSTGRES_DB=appflowy
export DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}

View File

@ -22,11 +22,11 @@ DB_USER="${POSTGRES_USER:=postgres}"
DB_PASSWORD="${POSTGRES_PASSWORD:=password}"
DB_PORT="${POSTGRES_PORT:=5432}"
DB_HOST="${POSTGRES_HOST:=localhost}"
DB_NAME="${POSTGRES_DB:=appflowy_pg}"
DB_NAME="${POSTGRES_DB:=appflowy}"
if [[ -z "${SKIP_DOCKER}" ]]
then
RUNNING_POSTGRES_CONTAINER=$(docker ps --filter 'name=postgres' --format '{{.ID}}')
RUNNING_POSTGRES_CONTAINER=$(docker ps --filter 'name=appflowy_postgres' --format '{{.ID}}')
if [[ -n $RUNNING_POSTGRES_CONTAINER ]]; then
echo >&2 "there is a postgres container already running, kill it with"
echo >&2 " docker kill ${RUNNING_POSTGRES_CONTAINER}"
@ -39,8 +39,8 @@ then
-e POSTGRES_DB="${DB_NAME}" \
-p "${DB_PORT}":5432 \
-d \
--name "af_postgres_$(date '+%s')" \
postgres -N 1000
--name "appflowy_postgres_$(date '+%s')" \
postgres:14 -N 1000
fi
@ -53,7 +53,7 @@ done
>&2 echo "Postgres is up and running on port ${DB_PORT} - running migrations now!"
export DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@localhost:${DB_PORT}/${DB_NAME}
export DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
sqlx database create
sqlx migrate run

View File

@ -2,7 +2,7 @@
set -x
set -eo pipefail
RUNNING_CONTAINER=$(docker ps --filter 'name=redis' --format '{{.ID}}')
RUNNING_CONTAINER=$(docker ps --filter 'name=appflowy_redis' --format '{{.ID}}')
if [[ -n $RUNNING_CONTAINER ]]; then
echo >&2 "there is a redis container already running, kill it with"
echo >&2 " docker kill ${RUNNING_CONTAINER}"
@ -13,7 +13,7 @@ fi
docker run \
-p "6379:6379" \
-d \
--name "redis_$(date '+%s')" \
--name "appflowy_redis_$(date '+%s')" \
redis:7
>&2 echo "Redis is ready to go!"

View File

@ -2,11 +2,11 @@ application:
port: 8000
host: 0.0.0.0
server_key: "Should-Use-The-Custom-Server-Key"
tls_config: "self_signed"
tls_config: "no_tls"
database:
host: "localhost"
port: 5432
username: "postgres"
password: "password"
database_name: "appflowy_pg"
database_name: "appflowy"
redis_uri: "redis://127.0.0.1:6379"

View File

@ -1,6 +1,8 @@
application:
host: 0.0.0.0
tls_config: "no_tls"
database:
host: "postgres_db"
host: "postgres"
port: 5432
require_ssl: false
redis_uri: "redis://redis:6379"

View File

@ -1,23 +1,27 @@
version: '3'
services:
postgres_db:
postgres:
image: postgres:14
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_HOST=${POSTGRES_HOST}
ports:
- "5432:5432"
- "5433:5432"
redis:
image: redis:7
ports:
- "6380:6379"
appflowy_server:
restart: on-failure
environment:
- APP_ENVIRONMENT=production
- DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}"
build:
context: ../../
dockerfile: ./services/appflowy_server/Dockerfile
dockerfile: ./Dockerfile
image: appflowy_server:${BACKEND_VERSION}
depends_on:
- postgres_db
- redis
- postgres
ports:
- 8000:8000

View File

@ -49,7 +49,15 @@ pub async fn run(
state: State,
config: Config,
) -> Result<Server, anyhow::Error> {
let redis_store = RedisSessionStore::new(config.redis_uri.expose_secret()).await?;
let redis_store = RedisSessionStore::new(config.redis_uri.expose_secret())
.await
.map_err(|e| {
anyhow::anyhow!(
"Failed to connect to Redis at {:?}: {:?}",
config.redis_uri,
e
)
})?;
let pair = get_certificate_and_server_key(&config);
let key = pair
.as_ref()
@ -85,6 +93,7 @@ pub async fn run(
fn get_certificate_and_server_key(config: &Config) -> Option<(Secret<String>, Secret<String>)> {
let tls_config = config.application.tls_config.as_ref()?;
match tls_config {
TlsConfig::NoTls => None,
TlsConfig::SelfSigned => Some(create_self_signed_certificate().unwrap()),
}
}

View File

@ -28,9 +28,22 @@ pub struct ApplicationSettings {
pub tls_config: Option<TlsConfig>,
}
impl ApplicationSettings {
pub fn use_https(&self) -> bool {
match &self.tls_config {
None => false,
Some(config) => match config {
TlsConfig::NoTls => false,
TlsConfig::SelfSigned => true,
},
}
}
}
#[derive(serde::Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum TlsConfig {
NoTls,
SelfSigned,
}

View File

@ -1,5 +1,5 @@
use appflowy_server::application::{init_state, Application};
use appflowy_server::config::config::{get_configuration, DatabaseSetting};
use appflowy_server::config::config::{get_configuration, DatabaseSetting, TlsConfig};
use appflowy_server::state::State;
use appflowy_server::telemetry::{get_subscriber, init_subscriber};
use once_cell::sync::Lazy;
@ -100,12 +100,18 @@ pub async fn spawn_server() -> TestServer {
.expect("Failed to build application");
let port = application.port();
let address = format!("https://localhost:{}", port);
let _ = tokio::spawn(async {
let _ = application.run_until_stopped().await;
});
let api_client = reqwest::Client::builder()
let mut builder = reqwest::Client::builder();
let mut address = format!("http://localhost:{}", port);
if config.application.use_https() {
address = format!("https://localhost:{}", port);
builder = builder.add_root_certificate(
Certificate::from_pem(include_bytes!("../../cert/cert.pem")).unwrap(),
);
}
let api_client = builder
.add_root_certificate(Certificate::from_pem(include_bytes!("../../cert/cert.pem")).unwrap())
.redirect(reqwest::redirect::Policy::none())
.danger_accept_invalid_certs(true)