Skip to content

Commit

Permalink
Add files for Docker build + embed migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
RubberDuckShobe committed Jul 3, 2024
1 parent c46500e commit 236e6a4
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 8 deletions.
12 changes: 12 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.env
.cargo/
.github/
.vscode/
radio/
target/
tests/
Dockerfile
scripts/
Wavebreaker.toml
WavebreakerRadio.toml
dump.rdb
62 changes: 60 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ tokio = "1.38"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
diesel = { version = "2.1", features = ["time"] }
diesel-async = { version = "0.4", features = ["postgres", "deadpool"] }
diesel-async = { version = "0.4.1", features = ["postgres", "deadpool", "async-connection-wrapper"] }
steam-rs = "0.4"
time = { version = "0.3", features = ["serde"] }
tower-http = { version = "0.5", features = ["fs", "trace"] }
Expand All @@ -33,3 +33,4 @@ redis = { version = "0.25", features = ["aio"] }
deadpool-redis = "0.15.1"
musicbrainz_rs = "0.5.0"
clap = { version = "4.5", features = ["derive"] }
diesel_migrations = { version = "2.1.0", features = ["postgres"] }
26 changes: 26 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# shoutout to Luca Palmieri
# https://www.lpalmieri.com/posts/2020-11-01-zero-to-production-5-how-to-deploy-a-rust-application

FROM rust:latest AS builder

# Let's switch our working directory to `app` (equivalent to `cd app`)
# The `app` folder will be created for us by Docker in case it does not
# exist already.
WORKDIR /app
# Install the required system dependencies for our linking configuration
RUN apt update && apt install lld clang -y
# Copy all files from our working environment to our Docker image
COPY . .
# Build in release mode
RUN cargo build --release

# Runtime stage
FROM debian:bookworm-slim AS runtime

WORKDIR /app
# Copy the compiled binary from the builder environment
# to our runtime environment
COPY --from=builder /app/target/release/wavebreaker wavebreaker
# OpenSSL isn't statically linked so we need to install it
RUN apt update && apt install openssl ca-certificates -y --no-install-recommends && apt autoremove -y && apt clean -y
ENTRYPOINT ["./wavebreaker"]
36 changes: 33 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ use axum::{
};
use clap::Parser;
use deadpool_redis::Runtime;
use diesel_async::pooled_connection::{deadpool::Pool, AsyncDieselConnectionManager};
use diesel::pg::Pg;
use diesel_async::{
async_connection_wrapper::AsyncConnectionWrapper,
pooled_connection::{deadpool::Pool, AsyncDieselConnectionManager},
};
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
use figment::{
providers::{Env, Format, Toml},
Figment,
Expand All @@ -40,6 +45,7 @@ use steam_rs::Steam;
use tower_http::trace::TraceLayer;
use tracing::{debug, info};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();

use crate::game::{routes_as, routes_steam_doubleslash};

Expand Down Expand Up @@ -75,14 +81,26 @@ pub struct AppState {
redis: deadpool_redis::Pool,
}

fn run_migrations(
connection: &mut impl MigrationHarness<Pg>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
// This will run the necessary migrations.
//
// See the documentation for `MigrationHarness` for
// all available methods.
connection.run_pending_migrations(MIGRATIONS)?;

Ok(())
}

/// Reads the config, initializes database connections and the Steam API client
///
/// # Returns
/// An `AppState` struct with all the necessary members
///
/// # Errors
/// This function can fail if the config file is missing or invalid, the connection to Postgres or Redis fails, or the Steam API key is invalid
fn init_state() -> anyhow::Result<AppState> {
async fn init_state() -> anyhow::Result<AppState> {
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
Expand All @@ -109,6 +127,18 @@ fn init_state() -> anyhow::Result<AppState> {
.build()
.context("Failed to build DB pool!")?;

// clone the url because moving the value will screw things up
let pg_url = wavebreaker_config.main.database.clone();
tokio::task::spawn_blocking(move || {
use diesel::prelude::Connection;
use diesel_async::pg::AsyncPgConnection;
let mut conn = AsyncConnectionWrapper::<AsyncPgConnection>::establish(&pg_url)
.expect("Failed to establish DB connection for migrations!");

run_migrations(&mut conn).expect("Failed to run migrations!");
})
.await?;

let redis_cfg = deadpool_redis::Config::from_url(&wavebreaker_config.main.redis);
let redis_pool = redis_cfg
.create_pool(Some(Runtime::Tokio1))
Expand Down Expand Up @@ -157,7 +187,7 @@ fn make_router(state: AppState) -> Router {

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let state = init_state()?;
let state = init_state().await?;

// Parse CLI arguments
// and if we have a management command, don't spin up a server
Expand Down
2 changes: 0 additions & 2 deletions src/models/players.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ use diesel::{
};
use diesel_async::{AsyncPgConnection, RunQueryDsl};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use redis::AsyncCommands;
use serde::Serialize;
use serde_repr::{Deserialize_repr, Serialize_repr};
use steam_rs::steam_id::SteamId;
use tracing::info;

use crate::{
models::{rivalries::Rivalry, scores::Score},
Expand Down

0 comments on commit 236e6a4

Please sign in to comment.