1use std::time::Duration;
4
5use serde::{Deserialize, Serialize};
6use sha2::Digest;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[non_exhaustive]
11pub enum RuntimeType {
12 Wasm,
14 Deno,
16}
17
18impl RuntimeType {
19 #[must_use]
21 pub const fn supported_extensions(&self) -> &[&str] {
22 match self {
23 RuntimeType::Wasm => &[".wasm"],
24 RuntimeType::Deno => &[".js", ".ts", ".mjs", ".mts"],
25 }
26 }
27}
28
29#[derive(Debug, Clone)]
31pub struct FunctionModule {
32 pub name: String,
34 pub source_hash: String,
36 pub bytecode: bytes::Bytes,
38 pub runtime: RuntimeType,
40}
41
42impl FunctionModule {
43 pub fn from_bytecode(name: String, bytecode: bytes::Bytes) -> Self {
45 let source_hash = format!("{:x}", sha2::Sha256::digest(&bytecode));
46 Self {
47 name,
48 source_hash,
49 bytecode,
50 runtime: RuntimeType::Wasm,
51 }
52 }
53
54 #[must_use]
56 pub fn from_source(name: String, source: String, runtime: RuntimeType) -> Self {
57 let bytecode = bytes::Bytes::from(source);
58 let source_hash = format!("{:x}", sha2::Sha256::digest(&bytecode));
59 Self {
60 name,
61 source_hash,
62 bytecode,
63 runtime,
64 }
65 }
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct EventPayload {
71 pub trigger_type: String,
73 pub entity: String,
75 pub event_kind: String,
77 pub data: serde_json::Value,
79 pub timestamp: chrono::DateTime<chrono::Utc>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct FunctionDefinition {
86 pub name: String,
88 pub trigger: String,
91 pub runtime: RuntimeType,
93 pub timeout_ms: Option<u64>,
97}
98
99impl FunctionDefinition {
100 #[must_use]
102 pub fn new(name: &str, trigger: &str, runtime: RuntimeType) -> Self {
103 Self {
104 name: name.to_string(),
105 trigger: trigger.to_string(),
106 runtime,
107 timeout_ms: None,
108 }
109 }
110
111 #[must_use]
113 pub const fn with_timeout(mut self, timeout_ms: u64) -> Self {
114 self.timeout_ms = Some(timeout_ms);
115 self
116 }
117
118 #[must_use]
120 pub fn effective_timeout(&self) -> Duration {
121 match self.timeout_ms {
122 Some(ms) => Duration::from_millis(ms),
123 None => {
124 if self.trigger.starts_with("before:mutation") {
126 Duration::from_millis(500)
127 } else {
128 Duration::from_secs(5)
129 }
130 },
131 }
132 }
133
134 #[must_use]
136 pub fn is_before_mutation(&self) -> bool {
137 self.trigger.starts_with("before:mutation:")
138 }
139
140 #[must_use]
142 pub fn is_after_mutation(&self) -> bool {
143 self.trigger.starts_with("after:mutation:")
144 }
145
146 #[must_use]
148 pub fn is_after_storage(&self) -> bool {
149 self.trigger.starts_with("after:storage:")
150 }
151
152 #[must_use]
154 pub fn is_cron(&self) -> bool {
155 self.trigger.starts_with("cron:")
156 }
157
158 #[must_use]
160 pub fn is_http(&self) -> bool {
161 self.trigger.starts_with("http:")
162 }
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
167#[non_exhaustive]
168pub enum LogLevel {
169 Debug,
171 Info,
173 Warn,
175 Error,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
181pub struct LogEntry {
182 pub level: LogLevel,
184 pub message: String,
186 pub timestamp: chrono::DateTime<chrono::Utc>,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct FunctionResult {
193 pub value: Option<serde_json::Value>,
195 pub logs: Vec<LogEntry>,
197 pub duration: Duration,
199 pub memory_peak_bytes: u64,
201}
202
203#[derive(Debug, Clone)]
205pub struct ResourceLimits {
206 pub max_memory_bytes: u64,
208 pub max_duration: Duration,
210 pub max_log_entries: usize,
212}
213
214impl Default for ResourceLimits {
215 fn default() -> Self {
216 Self {
217 max_memory_bytes: 128 * 1024 * 1024, max_duration: Duration::from_secs(5), max_log_entries: 10_000,
220 }
221 }
222}