mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-22 16:02:24 +00:00
39e0265389
* refactor: extract windmill-api into 4 subcrates (api-auth, store, api-sse, api-jobs) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: eliminate refresh_token OnceLock bridge in windmill-store Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: eliminate FromRequestParts OnceLock bridge in windmill-api-auth Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: wire subcrates into workspace and clean up unused re-exports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve cargo check --all-features errors in subcrate wiring Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * sqlx * all * chore: update ee-repo-ref for warning fixes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract windmill-trigger crate and expand windmill-api-jobs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract windmill-trigger-kafka crate from windmill-api Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract windmill-trigger-postgres crate from windmill-api Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract windmill-trigger-websocket and windmill-trigger-mqtt crates Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract windmill-trigger-nats, sqs, gcp, and email crates Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract windmill-trigger-http crate from windmill-api Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: move token creation and permission helpers to windmill-api-auth Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract windmill-native-triggers crate from windmill-api Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * sqlx * all * refactor: extract windmill-api-embeddings crate and fix CI warnings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: resolve type mismatch in oauth2_oss and remaining warnings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use correct HTTP_CLIENT config in embeddings crate (30s timeout, cert override) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * all * fix: gate oauth_refresh_ee on oauth2 feature to fix warnings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * all --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
127 lines
3.6 KiB
Rust
127 lines
3.6 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use windmill_api_auth::ApiAuthed;
|
|
use windmill_trigger::trigger_helpers::{
|
|
trigger_runnable_and_wait_for_raw_result_with_error_ctx, TriggerJobArgs,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::value::RawValue;
|
|
use sqlx::{types::Json as SqlxJson, FromRow};
|
|
use windmill_common::{
|
|
error::{Error, Result},
|
|
jobs::JobTriggerKind,
|
|
triggers::{TriggerKind, TriggerMetadata},
|
|
worker::to_raw_value,
|
|
DB,
|
|
};
|
|
use windmill_queue::PushArgsOwned;
|
|
|
|
pub mod handler;
|
|
pub mod listener;
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct WebsocketTrigger;
|
|
|
|
impl TriggerJobArgs for WebsocketTrigger {
|
|
type Payload = String;
|
|
const TRIGGER_KIND: TriggerKind = TriggerKind::Websocket;
|
|
fn v1_payload_fn(payload: &Self::Payload) -> HashMap<String, Box<RawValue>> {
|
|
HashMap::from([("msg".to_string(), to_raw_value(&payload))])
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
|
pub struct WebsocketConfig {
|
|
pub url: String,
|
|
#[serde(default)]
|
|
pub filters: Vec<SqlxJson<Box<RawValue>>>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub initial_messages: Option<Vec<SqlxJson<Box<RawValue>>>>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub url_runnable_args: Option<SqlxJson<Box<RawValue>>>,
|
|
#[serde(default)]
|
|
pub can_return_message: bool,
|
|
#[serde(default)]
|
|
pub can_return_error_result: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct WebsocketConfigRequest {
|
|
url: String,
|
|
filters: Vec<serde_json::Value>,
|
|
initial_messages: Option<Vec<serde_json::Value>>,
|
|
url_runnable_args: Option<serde_json::Value>,
|
|
can_return_message: bool,
|
|
can_return_error_result: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct TestWebsocketConfig {
|
|
url: String,
|
|
url_runnable_args: Option<serde_json::Value>,
|
|
}
|
|
|
|
pub fn value_to_args_hashmap(
|
|
args: Option<&Box<RawValue>>,
|
|
) -> Result<HashMap<String, Box<RawValue>>> {
|
|
let args = if let Some(args) = args {
|
|
let args_map: Option<HashMap<String, serde_json::Value>> = serde_json::from_str(args.get())
|
|
.map_err(|e| Error::BadRequest(format!("invalid json: {}", e)))?;
|
|
|
|
args_map
|
|
.unwrap_or_else(HashMap::new)
|
|
.into_iter()
|
|
.map(|(k, v)| {
|
|
let raw_value = serde_json::value::to_raw_value(&v).map_err(|e| {
|
|
Error::BadRequest(format!("failed to convert to raw value: {}", e))
|
|
})?;
|
|
Ok((k, raw_value))
|
|
})
|
|
.collect::<Result<HashMap<String, Box<RawValue>>>>()
|
|
} else {
|
|
Ok(HashMap::new())
|
|
}?;
|
|
Ok(args)
|
|
}
|
|
|
|
pub async fn get_url_from_runnable_value(
|
|
path: &str,
|
|
is_flow: bool,
|
|
db: &DB,
|
|
authed: ApiAuthed,
|
|
args: Option<&Box<RawValue>>,
|
|
workspace_id: &str,
|
|
) -> Result<String> {
|
|
tracing::info!(
|
|
"Running {} {} to get WebSocket URL",
|
|
if is_flow { "flow" } else { "script" },
|
|
path
|
|
);
|
|
|
|
let args = value_to_args_hashmap(args)?;
|
|
|
|
let result = trigger_runnable_and_wait_for_raw_result_with_error_ctx(
|
|
db,
|
|
None,
|
|
authed,
|
|
workspace_id,
|
|
path,
|
|
is_flow,
|
|
PushArgsOwned { args, extra: None },
|
|
None,
|
|
None,
|
|
None,
|
|
"".to_string(), // doesn't matter as no retry/error handler
|
|
TriggerMetadata::new(Some(path.to_owned()), JobTriggerKind::Websocket),
|
|
)
|
|
.await?;
|
|
|
|
serde_json::from_str::<String>(result.get()).map_err(|_| {
|
|
Error::BadConfig(format!(
|
|
"{} {} did not return a string",
|
|
if is_flow { "Flow" } else { "Script" },
|
|
path,
|
|
))
|
|
})
|
|
}
|