Skip to content

type annotations needed for RedisStorage<_> #600

@askareija

Description

@askareija

i tried to follow example for axum and implement it on my code. I'm separating main and infrastructure, here's my code for infrastructure.rs:

use crate::config::{
    app::{AppConfig, initialize_app_config},
    observability::initialize_observability,
};
use crate::utils::redis_client::RedisClient;
use crate::utils::s3_client::S3Client;

use anyhow::Context;
use apalis::prelude::*;
use apalis_redis::RedisStorage;
use migration::MigratorTrait;
use sea_orm::Database;

pub async fn initialize_infrastructure() -> anyhow::Result<(
    sea_orm::DatabaseConnection,
    RedisClient,
    AppConfig,
    S3Client,
)> {
    // SECTION: Memuat konfigurasi dari variabel environment
    let config = initialize_app_config().context("Failed to load application configuration")?;
    // !SECTION

    // SECTION: Menginisialisasi observability
    initialize_observability(&config.app_version).context("Failed to initialize OpenTelemetry")?;
    // !SECTION

    // SECTION: Setup koneksi database
    let db = Database::connect(&config.database_url)
        .await
        .context("Failed to connect to database")?;
    tracing::info!("Successfully connected to the database");
    // !SECTION

    // SECTION: Menjalankan migrasi database
    migration::Migrator::up(&db, None)
        .await
        .context("Failed to run database migrations")?;
    // !SECTION

    // SECTION: Setup koneksi Redis
    let redis_client = RedisClient::new(&config.redis_url)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to create Redis client: {:?}", e))?;
    // !SECTION

    // SECTION: Setup koneksi S3
    let s3_config = aws_config::load_from_env().await;
    let conf = aws_sdk_s3::config::Builder::from(&s3_config)
        .force_path_style(true)
        .build();
    let raw_s3_client = aws_sdk_s3::Client::from_conf(conf);
    let s3_client = S3Client::new(raw_s3_client).context("Failed to create S3 client wrapper")?;
    // !SECTION

    // SECTION: Setup Storage untuk apalis
    let redis_url = std::env::var("REDIS_URL").expect("Missing env variable REDIS_URL");
    let apalis_connection = apalis_redis::connect(redis_url)
        .await
        .expect("Cannot connect to redis");
    let apalis_storage = RedisStorage::new(apalis_connection);

    Ok((db, redis_client, config, s3_client))
}

and in main.rs:

mod config;
mod infrastructure;
mod jobs;
mod middlewares;
mod modules;
mod utils;

use std::{net::SocketAddr, process, sync::Arc, time::Duration};
use tokio::sync::Mutex;

use axum::http::{Request, Response};
use tower::ServiceBuilder;
use tower_http::trace::TraceLayer;
use tracing::Span;

use crate::{
    config::observability::{make_trace_span, trace_layer_on_response},
    infrastructure::initialize_infrastructure,
    utils::{app_state::AppState, router},
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // NOTE: Memuat file .env untuk konfigurasi environment
    match dotenvy::dotenv() {
        Ok(path) => tracing::info!("Loaded .env file from: {}", path.display()),
        Err(e) => {
            tracing::error!(
                "Could not load .env file: {}. Please ensure it exists in the root of the project.",
                e
            );
            tracing::warn!("Execution continues without loading .env file.");
        }
    };

    // NOTE: Menginisialisasi infrastruktur aplikasi
    let (db, redis_client, config, s3_client) = match initialize_infrastructure().await {
        Ok((db, redis_client, config, s3_client)) => (db, redis_client, config, s3_client),
        Err(error) => {
            tracing::error!("Error: Failed to initialize infrastructure: {:#}", error);
            process::exit(1);
        }
    };
    // !SECTION

    // NOTE: Membuat state aplikasi dengan semua dependensi
    let app_state = AppState {
        db,
        redis_client: Arc::new(Mutex::new(redis_client)),
        s3_client,
    };
    // !SECTION

    // NOTE: Membangun aplikasi dengan middleware dan routing
    let app = router::create_routes(app_state).layer(
        ServiceBuilder::new().layer(
            TraceLayer::new_for_http()
                .make_span_with(|request: &Request<_>| make_trace_span(request))
                .on_response(|response: &Response<_>, latency: Duration, span: &Span| {
                    trace_layer_on_response(response, latency, span)
                }),
        ),
    );

    // NOTE: Menjalankan server HTTP
    let addr = SocketAddr::new(config.app_host, config.app_port);
    tracing::info!("🚀 Server listening on {}", addr);

    let listener = tokio::net::TcpListener::bind(addr).await?;
    axum::serve(listener, app).await?;

    Ok(())
}

i've got error for RedisStorage::new, it's say:

type annotations needed for `RedisStorage<_>`
cannot satisfy `_: custom_error::_::_serde::Serialize`
the following types implement trait `custom_error::_::_serde::Serialize`:
  &'a T
  &'a mut T
  ()
  (T,)
  (T0, T1)
  (T0, T1, T2)
  (T0, T1, T2, T3)
  (T0, T1, T2, T3, T4)

how can i fix it?

my Cargo.toml:

# Background jobs
apalis = { version = "0.7", features = ["limit"] }
apalis-redis = "0.7"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions