From b106d4730f46c0eb5208cba9553798a31eef8282 Mon Sep 17 00:00:00 2001 From: pyranota Date: Tue, 28 Oct 2025 14:48:04 +0100 Subject: [PATCH] feat: mailbox Signed-off-by: pyranota --- .../20251028105101_mailbox.down.sql | 4 ++ .../migrations/20251028105101_mailbox.up.sql | 18 ++++++ backend/windmill-common/src/lib.rs | 1 + backend/windmill-common/src/mailbox.rs | 59 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 backend/migrations/20251028105101_mailbox.down.sql create mode 100644 backend/migrations/20251028105101_mailbox.up.sql create mode 100644 backend/windmill-common/src/mailbox.rs diff --git a/backend/migrations/20251028105101_mailbox.down.sql b/backend/migrations/20251028105101_mailbox.down.sql new file mode 100644 index 0000000000..21b2e759cd --- /dev/null +++ b/backend/migrations/20251028105101_mailbox.down.sql @@ -0,0 +1,4 @@ +-- Add down migration script here +DROP TABLE IF EXISTS mailbox; +DROP TYPE IF EXISTS mailbox_type; +DROP SEQUENCE IF EXISTS mailbox_id_seq; diff --git a/backend/migrations/20251028105101_mailbox.up.sql b/backend/migrations/20251028105101_mailbox.up.sql new file mode 100644 index 0000000000..201d494db9 --- /dev/null +++ b/backend/migrations/20251028105101_mailbox.up.sql @@ -0,0 +1,18 @@ +-- Add up migration script here +CREATE SEQUENCE IF NOT EXISTS mailbox_id_seq; + +CREATE TYPE mailbox_type AS ENUM ( + 'trigger', + 'debouncing_stale_data' +); + +CREATE TABLE mailbox( + message_id BIGINT DEFAULT nextval('mailbox_id_seq'), + mailbox_id TEXT, + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), -- Indicates position in stack + type mailbox_type NOT NULL, -- Type of mailbox + payload JSONB NOT NULL, -- Payload of specific message + PRIMARY KEY (message_id) +); + + diff --git a/backend/windmill-common/src/lib.rs b/backend/windmill-common/src/lib.rs index 53675c6ef4..64ffa66776 100644 --- a/backend/windmill-common/src/lib.rs +++ b/backend/windmill-common/src/lib.rs @@ -59,6 +59,7 @@ pub mod git_sync_ee; pub mod git_sync_oss; pub mod jobs; pub mod jwt; +pub mod mailbox; pub mod mcp_client; pub mod more_serde; pub mod oauth2; diff --git a/backend/windmill-common/src/mailbox.rs b/backend/windmill-common/src/mailbox.rs new file mode 100644 index 0000000000..b5817ecd0b --- /dev/null +++ b/backend/windmill-common/src/mailbox.rs @@ -0,0 +1,59 @@ +use sqlx::Postgres; + +use crate::error; + +pub struct Mailbox { + mailbox_id: Option, + mailbox_type: MailboxType, +} + +pub type MsgPayload = serde_json::Value; + +#[derive(sqlx::FromRow)] +pub struct MailboxMsg { + payload: MsgPayload, + created_at: chrono::DateTime, +} + +#[derive(sqlx::Type, Clone, Copy)] +#[sqlx(rename_all = "snake_case", type_name = "mailbox_type")] +pub enum MailboxType { + Trigger, + DebouncingStaleData, +} + +impl Mailbox { + pub fn open(mailbox_id: Option<&str>, mailbox_type: MailboxType) -> Self { + Self { mailbox_id: mailbox_id.map(str::to_owned), mailbox_type } + } + pub async fn push<'c>( + &self, + payload: MsgPayload, + e: impl sqlx::Executor<'c, Database = Postgres>, + ) -> error::Result<()> { + sqlx::query!( + r#"INSERT INTO mailbox(mailbox_id, type, payload) VALUES ($1, $2, $3)"#, + self.mailbox_id.as_ref(), + self.mailbox_type as MailboxType, + payload + ) + .execute(e) + .await?; + + Ok(()) + } + pub async fn pull<'c>( + &self, + e: impl sqlx::Executor<'c, Database = Postgres>, + ) -> error::Result> { + Ok(sqlx::query_as!( + MailboxMsg, + r#"DELETE FROM mailbox WHERE type = $1 AND mailbox_id = $2 RETURNING (message_id, created_at)"#, + self.mailbox_type as MailboxType, + self.mailbox_id.as_ref(), + ) + .fetch_optional(e) + .await?) + } + pub async fn pull_all() {} +}