mirror of
https://github.com/hanzoai/papers.git
synced 2026-10-22 17:20:17 +00:00
72 lines
2.9 KiB
TeX
72 lines
2.9 KiB
TeX
\section{Base Functions}
|
|
|
|
\label{sec:functions}
|
|
% ============================================================================
|
|
|
|
Base Functions are TypeScript functions that run inside the Base process. They
|
|
are not Lambda functions. They are not containers. They are JavaScript closures
|
|
executed in an embedded Goja VM, sharing the same process and the same database
|
|
connection as the rest of Base.
|
|
|
|
\subsection{Execution Model}
|
|
|
|
The Goja VM implements ECMAScript 2023. TypeScript is transpiled to JavaScript
|
|
at deploy time (via esbuild, also embedded in the binary). Functions execute
|
|
in response to events:
|
|
|
|
\begin{itemize}[leftmargin=1.1em]
|
|
\item \textbf{Before hooks}: Run before a database operation (create, update,
|
|
delete). Can modify the record or reject the operation.
|
|
\item \textbf{After hooks}: Run after a database operation. Used for
|
|
side effects (notifications, audit logs, cache invalidation).
|
|
\item \textbf{Routes}: Custom HTTP endpoints registered in the Base router.
|
|
Full access to request/response, database, and auth context.
|
|
\item \textbf{Cron}: Scheduled functions executed at configurable intervals.
|
|
Uses the Base internal scheduler, not system cron.
|
|
\item \textbf{Realtime}: Functions triggered by WebSocket subscription
|
|
events. Used for live data transformation.
|
|
\end{itemize}
|
|
|
|
\subsection{Zero Cold Start}
|
|
|
|
There is no cold start. The Goja VM is initialized once at Base startup and
|
|
persists for the lifetime of the process. Function invocation is a direct
|
|
Go function call into the VM---no process spawn, no container boot, no
|
|
network hop. Measured overhead per invocation: 0.3~ms for a trivial function,
|
|
1.2~ms for a function that reads 10 records and writes 1.
|
|
|
|
\begin{table}[H]
|
|
\centering
|
|
\small
|
|
\begin{tabular}{lrr}
|
|
\toprule
|
|
\textbf{Operation} & \textbf{Cold Start} & \textbf{Warm} \\
|
|
\midrule
|
|
AWS Lambda (Node.js) & 200--800~ms & 5--15~ms \\
|
|
Cloudflare Workers & 0~ms & 1--3~ms \\
|
|
Supabase Edge Functions & 50--200~ms & 3--8~ms \\
|
|
Base Functions (Goja) & 0~ms & 0.3--1.2~ms \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{Function invocation latency comparison. Base Functions have zero cold start because the VM is in-process.}
|
|
\label{tab:coldstart}
|
|
\end{table}
|
|
|
|
\subsection{Capability Model}
|
|
|
|
Functions execute with a capability set, not ambient authority. Each function
|
|
declares what it can access:
|
|
|
|
\begin{itemize}[leftmargin=1.1em]
|
|
\item \textbf{Collections}: Which collections the function can read/write.
|
|
\item \textbf{Network}: Whether the function can make outbound HTTP requests.
|
|
\item \textbf{KMS}: Whether the function can access encrypted fields.
|
|
\item \textbf{Auth}: Whether the function can read/modify user sessions.
|
|
\end{itemize}
|
|
|
|
A function that declares no capabilities can only compute on its inputs and
|
|
return a result. This is the default. Capabilities are additive, never
|
|
implicit.
|
|
|
|
% ============================================================================
|