Add proper shutdown, rate limits, config validation, cors config, fix dangling cursors, cache regex, merge created texts
This commit is contained in:
parent
4763bc9d04
commit
e15b0f9903
28 changed files with 1277 additions and 464 deletions
|
|
@ -1,5 +1,6 @@
|
|||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use anyhow::{Result, ensure};
|
||||
use log::debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
@ -34,6 +35,24 @@ fn default_cursor_timeout() -> Duration {
|
|||
DEFAULT_CURSOR_TIMEOUT
|
||||
}
|
||||
|
||||
impl DatabaseConfig {
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
ensure!(
|
||||
self.databases_directory_path.as_os_str().len() > 0,
|
||||
"databases_directory_path must not be empty"
|
||||
);
|
||||
ensure!(
|
||||
self.max_connections_per_vault > 0,
|
||||
"max_connections_per_vault must be greater than 0"
|
||||
);
|
||||
ensure!(
|
||||
!self.cursor_timeout.is_zero(),
|
||||
"cursor_timeout must be greater than 0"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DatabaseConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Result, ensure};
|
||||
use log::debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
@ -20,6 +21,17 @@ pub struct LoggingConfig {
|
|||
pub log_level: LogLevel,
|
||||
}
|
||||
|
||||
impl LoggingConfig {
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
ensure!(
|
||||
!self.log_directory.is_empty(),
|
||||
"log_directory must not be an empty string"
|
||||
);
|
||||
ensure!(self.log_rotation > 0, "log_rotation must be greater than 0");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LoggingConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
use anyhow::{Result, ensure};
|
||||
use log::debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::consts::{
|
||||
DEFAULT_HOST, DEFAULT_MAX_BODY_SIZE_MB, DEFAULT_MAX_CLIENTS_PER_VAULT,
|
||||
DEFAULT_MERGEABLE_FILE_EXTENSIONS, DEFAULT_PORT, DEFAULT_RESPONSE_TIMEOUT_SECONDS,
|
||||
DEFAULT_ALLOWED_ORIGINS, DEFAULT_BROADCAST_CHANNEL_CAPACITY, DEFAULT_HOST,
|
||||
DEFAULT_MAX_BODY_SIZE_MB, DEFAULT_MAX_CLIENTS_PER_VAULT, DEFAULT_MAX_PENDING_WS_CONNECTIONS,
|
||||
DEFAULT_MERGEABLE_FILE_EXTENSIONS, DEFAULT_PORT, DEFAULT_RATE_LIMIT_PER_USER_PER_SECOND,
|
||||
DEFAULT_RESPONSE_TIMEOUT_SECONDS,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
|
|
@ -21,11 +24,56 @@ pub struct ServerConfig {
|
|||
#[serde(default = "default_max_clients_per_vault")]
|
||||
pub max_clients_per_vault: usize,
|
||||
|
||||
#[serde(default = "default_broadcast_channel_capacity")]
|
||||
pub broadcast_channel_capacity: usize,
|
||||
|
||||
#[serde(default = "default_response_timeout", with = "humantime_serde")]
|
||||
pub response_timeout: Duration,
|
||||
|
||||
#[serde(default = "default_mergeable_file_extensions")]
|
||||
pub mergeable_file_extensions: Vec<String>,
|
||||
|
||||
/// Per-user maximum requests per second (keyed by bearer token).
|
||||
/// `None` disables rate limiting.
|
||||
#[serde(default = "DEFAULT_RATE_LIMIT_PER_USER_PER_SECOND")]
|
||||
pub rate_limit_per_user_per_second: Option<u64>,
|
||||
|
||||
/// Allowed CORS origins. Default: `["*"]` (allow all).
|
||||
#[serde(default = "default_allowed_origins")]
|
||||
pub allowed_origins: Vec<String>,
|
||||
|
||||
/// Maximum concurrent unauthenticated WebSocket connections waiting for
|
||||
/// handshake. Limits resource consumption from clients that connect but
|
||||
/// never authenticate.
|
||||
#[serde(default = "default_max_pending_websocket_connections")]
|
||||
pub max_pending_websocket_connections: usize,
|
||||
}
|
||||
|
||||
impl ServerConfig {
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
ensure!(
|
||||
self.response_timeout > 0,
|
||||
"response_timeout must be greater than 0"
|
||||
);
|
||||
ensure!(
|
||||
self.max_body_size_mb > 0,
|
||||
"max_body_size_mb must be greater than 0"
|
||||
);
|
||||
ensure!(
|
||||
self.max_clients_per_vault > 0,
|
||||
"max_clients_per_vault must be greater than 0"
|
||||
);
|
||||
ensure!(
|
||||
self.broadcast_channel_capacity > 0,
|
||||
"broadcast_channel_capacity must be greater than 0"
|
||||
);
|
||||
ensure!(
|
||||
self.max_pending_websocket_connections > 0,
|
||||
"max_pending_websocket_connections must be greater than 0"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn default_host() -> String {
|
||||
|
|
@ -48,6 +96,11 @@ fn default_max_clients_per_vault() -> usize {
|
|||
DEFAULT_MAX_CLIENTS_PER_VAULT
|
||||
}
|
||||
|
||||
fn default_broadcast_channel_capacity() -> usize {
|
||||
debug!("Using default broadcast channel capacity: {DEFAULT_BROADCAST_CHANNEL_CAPACITY}");
|
||||
DEFAULT_BROADCAST_CHANNEL_CAPACITY
|
||||
}
|
||||
|
||||
fn default_response_timeout() -> Duration {
|
||||
debug!("Using default response timeout: {DEFAULT_RESPONSE_TIMEOUT_SECONDS:?}");
|
||||
DEFAULT_RESPONSE_TIMEOUT_SECONDS
|
||||
|
|
@ -60,3 +113,21 @@ fn default_mergeable_file_extensions() -> Vec<String> {
|
|||
.map(|s| (*s).to_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn DEFAULT_RATE_LIMIT_PER_USER_PER_SECOND() -> Option<u64> {
|
||||
debug!("Using default rate limit per second: {DEFAULT_RATE_LIMIT_PER_USER_PER_SECOND:?}");
|
||||
DEFAULT_RATE_LIMIT_PER_USER_PER_SECOND
|
||||
}
|
||||
|
||||
fn default_allowed_origins() -> Vec<String> {
|
||||
debug!("Using default allowed origins: {DEFAULT_ALLOWED_ORIGINS:?}");
|
||||
DEFAULT_ALLOWED_ORIGINS
|
||||
.iter()
|
||||
.map(|s| (*s).to_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn default_max_pending_websocket_connections() -> usize {
|
||||
debug!("Using default max pending WebSocket connections: {DEFAULT_MAX_PENDING_WS_CONNECTIONS}");
|
||||
DEFAULT_MAX_PENDING_WS_CONNECTIONS
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue