Skip to content

Commit

Permalink
fix(repo): use cli instead of config.toml
Browse files Browse the repository at this point in the history
  • Loading branch information
pedronauck committed Dec 19, 2024
1 parent 71119fa commit 95f388c
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 191 deletions.
18 changes: 16 additions & 2 deletions .github/workflows/docker_publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ name: Build and publish Docker image

on:
workflow_dispatch:
inputs:
image_type:
description: "Choose which image to build (publisher/webserver/both)"
required: true
type: choice
options:
- publisher
- webserver
- both
default: "both"
push:
branches:
- main
Expand Down Expand Up @@ -32,7 +42,9 @@ jobs:
id: sha
run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT

- name: Build and push Docker (${{ steps.sha.outputs.short_sha }}) for publisher
- name: Build and push Docker for publisher
if: github.event.inputs.image_type == 'publisher' || github.event.inputs.image_type == 'both'
|| github.event_name != 'workflow_dispatch'
uses: ./.github/actions/docker-publish
id: publish-fuel-streams-nats
with:
Expand All @@ -41,7 +53,9 @@ jobs:
image: ghcr.io/fuellabs/fuel-streams-publisher
dockerfile: cluster/docker/fuel-streams-publisher.Dockerfile

- name: Build and push Docker (${{ steps.sha.outputs.short_sha }}) for webserver
- name: Build and push Docker for webserver
if: github.event.inputs.image_type == 'webserver' || github.event.inputs.image_type == 'both'
|| github.event_name != 'workflow_dispatch'
uses: ./.github/actions/docker-publish
id: publish-fuel-webserver-nats
with:
Expand Down
14 changes: 0 additions & 14 deletions crates/fuel-streams-ws/config.toml

This file was deleted.

63 changes: 55 additions & 8 deletions crates/fuel-streams-ws/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,64 @@
use clap::Parser;

/// CLI structure for parsing command-line arguments.
///
/// - `config_path`: Path to the toml config file.
#[derive(Clone, Parser)]
pub struct Cli {
/// Config path
/// API port number
#[arg(
long,
value_name = "CONFIG",
env = "CONFIG_PATH",
default_value = "config.toml",
help = "Path to toml config file"
value_name = "PORT",
env = "API_PORT",
default_value = "9003",
help = "Port number for the API server"
)]
pub config_path: Option<String>,
pub api_port: u16,

/// NATS URL
#[arg(
long,
value_name = "NATS_URL",
env = "NATS_URL",
default_value = "nats://localhost:4222",
help = "NATS URL"
)]
pub nats_url: String,

/// Fuel network configuration
#[arg(
long,
value_name = "NETWORK",
env = "NETWORK",
default_value = "local",
help = "Fuel network configuration (local, etc.)"
)]
pub network: String,

/// Enable S3
#[arg(
long,
value_name = "AWS_S3_ENABLED",
env = "AWS_S3_ENABLED",
default_value = "true",
help = "Enable S3 integration"
)]
pub s3_enabled: bool,

/// JWT secret
#[arg(
long,
value_name = "JWT_AUTH_SECRET",
env = "JWT_AUTH_SECRET",
default_value = "secret",
help = "Secret key for JWT authentication"
)]
pub jwt_secret: String,

/// Use metrics
#[arg(
long,
env = "USE_METRICS",
default_value = "false",
help = "Enable metrics"
)]
pub use_metrics: bool,
}
161 changes: 25 additions & 136 deletions crates/fuel-streams-ws/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,79 +1,49 @@
use std::{
num::ParseIntError,
path::{Path, PathBuf},
str::{FromStr, ParseBoolError},
time::Duration,
};
use std::{path::PathBuf, str::FromStr};

use confy::ConfyError;
use clap::Parser;
use displaydoc::Display as DisplayDoc;
use fuel_streams::types::FuelNetwork;
use serde::{Deserialize, Deserializer};
use thiserror::Error;
use tokio::{fs::File, io::AsyncReadExt};

#[derive(Debug, DisplayDoc, Error)]
pub enum Error {
/// Open config file: {0}
OpenConfig(std::io::Error),
/// Failed to parse config: {0}
ParseConfig(toml::de::Error),
/// Failed to parse config as utf-8: {0}
ParseUtf8(std::string::FromUtf8Error),
/// Failed to read config file: {0}
ReadConfig(std::io::Error),
/// Failed to read config metadata: {0}
ReadMeta(std::io::Error),
/// Failed to read env config: {0}
Confy(ConfyError),
/// Undecodable config element: {0}
UndecodableConfigElement(&'static str),
/// Parse int error: {0}
ParseInt(ParseIntError),
/// Parse bool error: {0}
ParseBool(ParseBoolError),
}

#[derive(Debug, Default, Deserialize, Clone)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[derive(Debug, Default, Clone)]
pub struct S3Config {
pub enabled: bool,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[derive(Clone, Debug)]
pub struct TlsConfig {
pub private_key: PathBuf,
pub certificate: PathBuf,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[derive(Clone, Debug)]
pub struct ApiConfig {
pub port: u16,
pub tls: Option<TlsConfig>,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[derive(Clone, Debug)]
pub struct AuthConfig {
pub jwt_secret: String,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[derive(Clone, Debug)]
pub struct FuelConfig {
pub network: FuelNetwork,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[derive(Clone, Debug)]
pub struct NatsConfig {
pub network: FuelNetwork,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[derive(Clone, Debug)]
pub struct Config {
pub api: ApiConfig,
pub auth: AuthConfig,
Expand All @@ -82,112 +52,31 @@ pub struct Config {
pub fuel: FuelConfig,
}

impl Default for Config {
fn default() -> Self {
Config {
impl Config {
pub fn load() -> Result<Self, Error> {
let cli = crate::cli::Cli::parse();
Self::from_cli(&cli)
}

fn from_cli(cli: &crate::cli::Cli) -> Result<Self, Error> {
Ok(Config {
api: ApiConfig {
port: 9003,
port: cli.api_port,
tls: None,
},
auth: AuthConfig {
jwt_secret: String::new(),
jwt_secret: cli.jwt_secret.clone(),
},
nats: NatsConfig {
network: FuelNetwork::Local,
},
s3: S3Config { enabled: false },
s3: S3Config {
enabled: cli.s3_enabled,
},
fuel: FuelConfig {
network: FuelNetwork::Local,
network: FuelNetwork::from_str(&cli.network)
.map_err(|_| Error::UndecodableConfigElement("NETWORK"))?,
},
}
}
}

#[allow(dead_code)]
fn deserialize_duration_from_usize<'de, D>(
deserializer: D,
) -> Result<Duration, D::Error>
where
D: Deserializer<'de>,
{
let seconds = u64::deserialize(deserializer)?;
Ok(Duration::from_secs(seconds))
}

#[allow(dead_code)]
fn deserialize_duration_option<'de, D>(
deserializer: D,
) -> Result<Option<Duration>, D::Error>
where
D: Deserializer<'de>,
{
let seconds: Option<u64> = Option::deserialize(deserializer)?;
if seconds.is_none() {
return Ok(None);
}
Ok(seconds.map(Duration::from_secs))
}

impl Config {
pub async fn from_path(
path: impl AsRef<Path> + Send,
) -> Result<Self, Error> {
read_to_string(path).await?.parse()
})
}

pub fn from_envs() -> Result<Self, Error> {
let mut config = Self::default();

// ----------------------API--------------------------------
if let Ok(app_port) = dotenvy::var("STREAMER_API_PORT") {
config.api.port =
app_port.parse::<u16>().map_err(Error::ParseInt)?;
}

// ----------------------NATS--------------------------------
if let Ok(nats_network) = dotenvy::var("NETWORK") {
config.nats.network = FuelNetwork::from_str(&nats_network)
.map_err(|_| Error::UndecodableConfigElement("NETWORK"))?;
}

// ----------------------S3--------------------------------
if let Ok(s3_enabled) = dotenvy::var("AWS_S3_ENABLED") {
config.s3.enabled =
s3_enabled.parse::<bool>().map_err(Error::ParseBool)?;
}

// ----------------------AUTH--------------------------------
if let Ok(jwt_secret) = dotenvy::var("JWT_AUTH_SECRET") {
config.auth.jwt_secret = jwt_secret;
}

// ----------------------FUEL--------------------------------
if let Ok(network) = dotenvy::var("NETWORK") {
config.fuel.network = FuelNetwork::from_str(&network)
.map_err(|_| Error::UndecodableConfigElement("NETWORK"))?;
}

Ok(config)
}
}

impl FromStr for Config {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
toml::from_str(s).map_err(Error::ParseConfig)
}
}

async fn read_to_string(
path: impl AsRef<Path> + Send,
) -> Result<String, Error> {
let mut file = File::open(path).await.map_err(Error::OpenConfig)?;
let meta = file.metadata().await.map_err(Error::ReadMeta)?;
let mut contents =
Vec::with_capacity(usize::try_from(meta.len()).unwrap_or(0));
file.read_to_end(&mut contents)
.await
.map_err(Error::ReadConfig)?;
String::from_utf8(contents).map_err(Error::ParseUtf8)
}
4 changes: 2 additions & 2 deletions crates/fuel-streams-ws/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ pub mod config;
pub mod server;
pub mod telemetry;

use std::{env, sync::LazyLock};
use std::sync::LazyLock;

pub static STREAMER_MAX_WORKERS: LazyLock<usize> = LazyLock::new(|| {
let available_cpus = num_cpus::get();
let default_threads = 2 * available_cpus;

env::var("STREAMER_MAX_WORKERS")
dotenvy::var("STREAMER_MAX_WORKERS")
.ok()
.and_then(|val| val.parse().ok())
.unwrap_or(default_threads)
Expand Down
Loading

0 comments on commit 95f388c

Please sign in to comment.