Skip to content

Commit bb0e39a

Browse files
committed
feat: Various minor improvements
- Parameter order consistency. - Further `TaskTracker` adoption. - Exit early if no plugin initializes successfully. - Move the log CLI arguments to the bottom and simplify argument help messages.
1 parent 6915a13 commit bb0e39a

8 files changed

Lines changed: 53 additions & 45 deletions

File tree

src/cli.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@ impl From<String> for CliLogParametersFileRotation {
2424
#[derive(Parser)]
2525
#[command(about, long_about = None, version, author)]
2626
pub struct Cli {
27-
#[command(flatten)]
28-
pub log_parameters: CliLogParameters,
29-
3027
#[arg(default_value = "./config.yaml", short, long, value_name = "FILE PATH", help = "The path to the program its configuration file", long_help = None)]
3128
pub config_file: PathBuf,
3229

33-
#[arg(default_value = "./.env", short, long, value_name = "FILE PATH", help = "The path to an env file, used by the program its configuration file for env var interpolation", long_help = None)]
30+
#[arg(default_value = "./.env", short, long, value_name = "FILE PATH", help = "The path to the program its env file", long_help = None)]
3431
pub env_file: PathBuf,
3532

3633
#[arg(default_value = "./plugins", short, long, value_name = "DIRECTORY PATH", help = "The path to the program its plugin directory", long_help = None)]
@@ -41,6 +38,9 @@ pub struct Cli {
4138

4239
#[arg(default_value_t = false, short, long, help = "Run in restricted mode, in this case plugin permissions are opt in", long_help = None)]
4340
pub restricted: bool,
41+
42+
#[command(flatten)]
43+
pub log_parameters: CliLogParameters,
4444
}
4545

4646
#[derive(Args)]

src/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{collections::HashMap, fs, path::Path};
66
use anyhow::Result;
77
use serde::Deserialize;
88
use tracing::info;
9+
use uuid::Uuid;
910

1011
use crate::config::{plugins::ConfigPlugin, services::ConfigServices};
1112

@@ -14,13 +15,18 @@ pub mod services;
1415

1516
#[derive(Deserialize)]
1617
pub struct Config {
18+
#[serde(default = "Config::default_name")]
1719
pub name: String,
1820
#[serde(default)]
1921
pub services: ConfigServices,
2022
pub plugins: HashMap<String, ConfigPlugin>,
2123
}
2224

2325
impl Config {
26+
fn default_name() -> String {
27+
Uuid::new_v4().to_string()
28+
}
29+
2430
pub fn new(file_path: &Path, restricted: bool) -> Result<Self> {
2531
info!("Loading and parsing the config file");
2632

src/main.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,21 @@ async fn main() -> Result<ExitCode> {
101101
let database = database::new(&cli.database_directory)?;
102102

103103
let message_handler = message_handler(
104-
database.clone(),
105104
Arc::new(RwLock::new(Some(channels.core.runtime_tx))),
106105
Arc::new(RwLock::new(channels.core.job_scheduler_tx)),
107106
Arc::new(RwLock::new(channels.core.discord_tx)),
108-
Arc::new(shutdown_signal_listener),
109107
channels.core.rx,
108+
database.clone(),
109+
Arc::new(shutdown_signal_listener),
110110
);
111111

112112
let setup_result = setup(
113113
cli.plugin_directory,
114-
database,
115-
channels.services,
116-
channels.runtime,
117114
config,
118115
secrets,
116+
channels.services,
117+
channels.runtime,
118+
database,
119119
)
120120
.await;
121121

@@ -129,12 +129,12 @@ async fn main() -> Result<ExitCode> {
129129
}
130130

131131
fn message_handler(
132-
database: Database,
133132
runtime_tx: Arc<RwLock<Option<UnboundedSender<RuntimeMessages>>>>,
134133
job_scheduler_tx: Arc<RwLock<Option<UnboundedSender<JobSchedulerMessages>>>>,
135134
discord_tx: Arc<RwLock<Option<UnboundedSender<DiscordMessages>>>>,
136-
shutdown_signal_listener: Arc<JoinHandle<()>>,
137135
mut rx: UnboundedReceiver<CoreMessages>,
136+
database: Database,
137+
shutdown_signal_listener: Arc<JoinHandle<()>>,
138138
) -> JoinHandle<Result<()>> {
139139
debug!("Starting the message handler");
140140

@@ -158,11 +158,11 @@ fn message_handler(
158158
}
159159
CoreMessages::Shutdown(shutdown_kind) => {
160160
tokio::spawn(shutdown(
161-
shutdown_kind,
162161
runtime_tx.clone(),
163162
job_scheduler_tx.clone(),
164163
discord_tx.clone(),
165164
shutdown_signal_listener.clone(),
165+
shutdown_kind,
166166
));
167167
}
168168
}
@@ -174,27 +174,27 @@ fn message_handler(
174174

175175
async fn setup(
176176
plugin_directory_path: PathBuf,
177-
database: Database,
178-
service_channels: ChannelsServices,
179-
runtime_channels: ChannelsRuntime,
180177
config: Config,
181178
secrets: Secrets,
179+
service_channels: ChannelsServices,
180+
runtime_channels: ChannelsRuntime,
181+
database: Database,
182182
) -> Result<()> {
183183
let config_name = Arc::new(config.name);
184184

185185
let available_plugins = registry::get_plugins(
186186
&plugin_directory_path,
187-
database.clone(),
188187
config_name.clone(),
189188
config.plugins,
189+
database.clone(),
190190
)
191191
.await?;
192192

193193
services::setup(
194194
config.services,
195195
secrets.services,
196-
database.clone(),
197196
service_channels,
197+
database.clone(),
198198
)
199199
.await?;
200200

@@ -204,9 +204,9 @@ async fn setup(
204204
.initialize_plugins(
205205
plugin_directory_path,
206206
config_name,
207-
available_plugins,
208-
database,
209207
runtime_channels.core_tx,
208+
database,
209+
available_plugins,
210210
)
211211
.await?;
212212

@@ -293,11 +293,11 @@ fn shutdown_signal_listener(core_tx: UnboundedSender<CoreMessages>) -> JoinHandl
293293
}
294294

295295
async fn shutdown(
296-
shutdown_kind: Shutdown,
297296
runtime_tx: Arc<RwLock<Option<UnboundedSender<RuntimeMessages>>>>,
298297
job_scheduler_tx: Arc<RwLock<Option<UnboundedSender<JobSchedulerMessages>>>>,
299298
discord_tx: Arc<RwLock<Option<UnboundedSender<DiscordMessages>>>>,
300299
shutdown_signal_listener: Arc<JoinHandle<()>>,
300+
shutdown_kind: Shutdown,
301301
) {
302302
let mut shutdown_guard = SHUTDOWN.write().await;
303303

src/registry.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ static DEFAULT_NAMESPACE_ID: &str = "wpbs-rs";
2727
#[hotpath::measure]
2828
pub async fn get_plugins(
2929
plugin_directory_path: &Path,
30-
database: Database,
3130
config_name: Arc<String>,
3231
config_plugins: HashMap<String, ConfigPlugin>,
32+
database: Database,
3333
) -> Result<Vec<(Uuid, AvailablePlugin)>> {
3434
info!("Getting all plugins from their respective registries");
3535

src/runtime.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub mod plugins;
66

77
use std::{collections::HashMap, path::PathBuf, sync::Arc};
88

9-
use anyhow::Result;
9+
use anyhow::{Result, bail};
1010
use fjall::Database;
1111
use tokio::{
1212
fs,
@@ -172,26 +172,25 @@ impl Runtime {
172172
&self,
173173
plugins_directory_path: PathBuf,
174174
config_name: Arc<String>,
175-
available_plugins: Vec<(Uuid, AvailablePlugin)>,
176-
database: Database,
177175
core_tx: UnboundedSender<CoreMessages>,
176+
database: Database,
177+
available_plugins: Vec<(Uuid, AvailablePlugin)>,
178178
) -> Result<()> {
179179
info!("Initializing the plugins");
180180

181181
let plugins_directory_path = Arc::new(plugins_directory_path);
182182

183-
let mut tasks = Vec::new();
183+
let task_tracker = TaskTracker::new();
184184

185-
// TODO: Bail on no successful plugin initializations
186185
for (plugin_uuid, plugin_metadata) in available_plugins {
187186
let plugins_directory_path = plugins_directory_path.clone();
188187
let config_name = config_name.clone();
189-
let plugins = self.plugins.clone();
190-
let plugin_builder = self.plugin_builder.clone();
191188
let database = database.clone();
192189
let core_tx = core_tx.clone();
190+
let plugins = self.plugins.clone();
191+
let plugin_builder = self.plugin_builder.clone();
193192

194-
tasks.push(tokio::spawn(async move {
193+
task_tracker.spawn(async move {
195194
let plugin_binary_path = if let Some(content_digest) = &plugin_metadata.content_digest {
196195
match content_digest {
197196
ContentDigest::Sha256 { hex } => plugins_directory_path.join("binaries").join("remote").join(format!("sha256:{hex}"))
@@ -205,7 +204,7 @@ impl Runtime {
205204
.join(plugin_metadata.version.to_string()).join("plugin.wasm")
206205
};
207206

208-
// TODO: Make this configurable
207+
// TODO: Make workspaces configurable
209208
let plugin_workspace_path = plugins_directory_path
210209
.join("workspaces")
211210
.join(&*config_name)
@@ -326,11 +325,14 @@ impl Runtime {
326325
});
327326

328327
plugins.write().await.insert(plugin_uuid, plugin_context);
329-
}));
328+
});
330329
}
331330

332-
for task in tasks {
333-
task.await.unwrap();
331+
task_tracker.close();
332+
task_tracker.wait().await;
333+
334+
if self.plugins.read().await.is_empty() {
335+
bail!("No plugin initialized successfully")
334336
}
335337

336338
Ok(())

src/services.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub mod job_scheduler;
2121
pub async fn setup(
2222
config: ConfigServices,
2323
secrets: SecretsServices,
24-
database: Database,
2524
channels: ChannelsServices,
25+
database: Database,
2626
) -> Result<()> {
2727
// TODO:
2828
// - Make service starts concurrent
@@ -39,9 +39,9 @@ pub async fn setup(
3939
let discord = Discord::new(
4040
config.discord.settings,
4141
secrets.discord.unwrap(),
42-
database,
4342
discord_channels.core_tx,
4443
discord_channels.rx,
44+
database,
4545
)
4646
.await?;
4747

src/services/discord.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ impl Discord {
4949
pub async fn new(
5050
config: ConfigDiscordSettings,
5151
secrets: SecretsDiscord,
52-
database: Database,
5352
core_tx: UnboundedSender<CoreMessages>,
5453
rx: UnboundedReceiver<DiscordMessages>,
54+
database: Database,
5555
) -> Result<Self> {
5656
info!("Creating the Discord service");
5757

@@ -109,17 +109,17 @@ impl Discord {
109109
pub fn run(mut self) -> JoinHandle<()> {
110110
info!("Starting the Discord service");
111111

112-
let mut shard_tasks = Vec::with_capacity(self.shards.len());
112+
let shard_task_tracker = TaskTracker::new();
113113
let http_task_tracker = TaskTracker::new();
114114

115115
for shard in self.shards.drain(..) {
116-
shard_tasks.push(tokio::spawn(Self::shard_runner(
116+
shard_task_tracker.spawn(Self::shard_runner(
117117
self.database.clone(),
118118
self.cache.clone(),
119119
self.core_tx.clone(),
120120
shard.0,
121121
shard.1,
122-
)));
122+
));
123123
}
124124

125125
tokio::spawn(async move {
@@ -152,7 +152,7 @@ impl Discord {
152152
http_task_tracker.close();
153153
http_task_tracker.wait().await;
154154

155-
self.shutdown(shard_tasks).await;
155+
self.shutdown(shard_task_tracker).await;
156156
})
157157
}
158158

@@ -187,15 +187,14 @@ impl Discord {
187187
}
188188
}
189189

190-
async fn shutdown(&self, tasks: Vec<JoinHandle<()>>) {
190+
async fn shutdown(&self, shard_task_tracker: TaskTracker) {
191191
info!("Shutting the Discord service down");
192192

193193
for shard_message_sender in self.shard_message_senders.iter() {
194-
_ = shard_message_sender.close(CloseFrame::NORMAL);
194+
let _ = shard_message_sender.close(CloseFrame::NORMAL);
195195
}
196196

197-
for task in tasks {
198-
task.await.unwrap();
199-
}
197+
shard_task_tracker.close();
198+
shard_task_tracker.wait().await;
200199
}
201200
}

src/services/discord/requests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::{
2323
};
2424

2525
impl Discord {
26+
// TODO: Split up in sub functions
2627
#[allow(clippy::too_many_lines)]
2728
pub async fn request(
2829
http_client: Arc<Client>,

0 commit comments

Comments
 (0)