use std::time::Duration;
use serde::{Deserialize, Serialize};
use sha2::Digest;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum RuntimeType {
Wasm,
Deno,
}
impl RuntimeType {
#[must_use]
pub const fn supported_extensions(&self) -> &[&str] {
match self {
RuntimeType::Wasm => &[".wasm"],
RuntimeType::Deno => &[".js", ".ts", ".mjs", ".mts"],
}
}
}
#[derive(Debug, Clone)]
pub struct FunctionModule {
pub name: String,
pub source_hash: String,
pub bytecode: bytes::Bytes,
pub runtime: RuntimeType,
}
impl FunctionModule {
pub fn from_bytecode(name: String, bytecode: bytes::Bytes) -> Self {
let source_hash = format!("{:x}", sha2::Sha256::digest(&bytecode));
Self {
name,
source_hash,
bytecode,
runtime: RuntimeType::Wasm,
}
}
#[must_use]
pub fn from_source(name: String, source: String, runtime: RuntimeType) -> Self {
let bytecode = bytes::Bytes::from(source);
let source_hash = format!("{:x}", sha2::Sha256::digest(&bytecode));
Self {
name,
source_hash,
bytecode,
runtime,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EventPayload {
pub trigger_type: String,
pub entity: String,
pub event_kind: String,
pub data: serde_json::Value,
pub timestamp: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionDefinition {
pub name: String,
pub trigger: String,
pub runtime: RuntimeType,
pub timeout_ms: Option<u64>,
}
impl FunctionDefinition {
#[must_use]
pub fn new(name: &str, trigger: &str, runtime: RuntimeType) -> Self {
Self {
name: name.to_string(),
trigger: trigger.to_string(),
runtime,
timeout_ms: None,
}
}
#[must_use]
pub const fn with_timeout(mut self, timeout_ms: u64) -> Self {
self.timeout_ms = Some(timeout_ms);
self
}
#[must_use]
pub fn effective_timeout(&self) -> Duration {
match self.timeout_ms {
Some(ms) => Duration::from_millis(ms),
None => {
if self.trigger.starts_with("before:mutation") {
Duration::from_millis(500)
} else {
Duration::from_secs(5)
}
},
}
}
#[must_use]
pub fn is_before_mutation(&self) -> bool {
self.trigger.starts_with("before:mutation:")
}
#[must_use]
pub fn is_after_mutation(&self) -> bool {
self.trigger.starts_with("after:mutation:")
}
#[must_use]
pub fn is_after_storage(&self) -> bool {
self.trigger.starts_with("after:storage:")
}
#[must_use]
pub fn is_cron(&self) -> bool {
self.trigger.starts_with("cron:")
}
#[must_use]
pub fn is_http(&self) -> bool {
self.trigger.starts_with("http:")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum LogLevel {
Debug,
Info,
Warn,
Error,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LogEntry {
pub level: LogLevel,
pub message: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionResult {
pub value: Option<serde_json::Value>,
pub logs: Vec<LogEntry>,
pub duration: Duration,
pub memory_peak_bytes: u64,
}
#[derive(Debug, Clone)]
pub struct ResourceLimits {
pub max_memory_bytes: u64,
pub max_duration: Duration,
pub max_log_entries: usize,
}
impl Default for ResourceLimits {
fn default() -> Self {
Self {
max_memory_bytes: 128 * 1024 * 1024, max_duration: Duration::from_secs(5), max_log_entries: 10_000,
}
}
}