Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions services/ws-modules/pydata1/pkg/et_ws_pydata1.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// Interface: default(wasmUrl), metadata(), run()

const PYODIDE_BASE_PATH = "/modules/pyodide/";
// ES-module entry used by the Deno / non-browser `import()` path below (its named export is `loadPyodide`);
// the browser path loads the UMD `pyodide.js` via a <script> tag instead.
const PYODIDE_CDN = `${PYODIDE_BASE_PATH}pyodide.mjs`;

Check warning on line 7 in services/ws-modules/pydata1/pkg/et_ws_pydata1.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

services/ws-modules/pydata1/pkg/et_ws_pydata1.js#L7

ES2015 block-scoped variables are forbidden.

Check warning on line 7 in services/ws-modules/pydata1/pkg/et_ws_pydata1.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

services/ws-modules/pydata1/pkg/et_ws_pydata1.js#L7

ES2015 template literals are forbidden.

let pyodide = null;
let pyMod = null;
Expand Down
12 changes: 7 additions & 5 deletions services/ws/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::collections::BTreeMap;
use std::sync::LazyLock;
use std::sync::{Arc, LazyLock};
use std::time::{Duration, Instant};

use actix_web::{Error, HttpRequest, HttpResponse, web};
Expand Down Expand Up @@ -108,7 +108,7 @@ const fn default_connection_timeout() -> Option<Duration> {
#[non_exhaustive]
pub enum SessionMessage {
Json(ServerMessage),
Text(String),
Text(Arc<str>),
Binary(Bytes),
}

Expand Down Expand Up @@ -242,8 +242,8 @@ impl Connection {
}
}

async fn send_text(&mut self, text: String) {
if let Err(err) = self.session.text(text).await {
async fn send_text(&mut self, text: Arc<str>) {
if let Err(err) = self.session.text(text.as_ref()).await {
warn!("Failed to forward text to {}: {:?}", self.current_agent_id(), err);
}
}
Expand Down Expand Up @@ -366,8 +366,10 @@ impl Connection {
from_agent_id,
recipients.len()
);
// Allocate the payload once; each session gets a cheap Arc clone instead of a per-recipient String.
let payload: Arc<str> = Arc::from(text);
for (_, recipient) in recipients {
let _sent = recipient.send(SessionMessage::Text(text.to_string()));
let _sent = recipient.send(SessionMessage::Text(Arc::clone(&payload)));
}
}

Expand Down
2 changes: 2 additions & 0 deletions utilities/int-gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ pub enum Error {
UnsupportedSchemaType(String),
#[error("enum value not a string in `{0}`")]
EnumValueNotString(String),
#[error("conflicting schema definitions for `$defs/{0}` between client and server schemas")]
ConflictingDefs(String),
#[error("progenitor codegen: {0}")]
Progenitor(String),
#[error("zig codegen: {0}")]
Expand Down
14 changes: 11 additions & 3 deletions utilities/int-gen/src/wit/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type EnumSet = HashSet<String>;
pub fn render(client_schema: &Schema, server_schema: &Schema) -> Result<String, Error> {
let client_root = client_schema.as_value();
let server_root = server_schema.as_value();
let merged_root = merge_defs(client_root, server_root);
let merged_root = merge_defs(client_root, server_root)?;
let mut interface = Interface::new("messages");
interface.set_docs(Some(WS_DESCRIPTION));

Expand Down Expand Up @@ -77,11 +77,19 @@ pub fn render(client_schema: &Schema, server_schema: &Schema) -> Result<String,
clippy::single_call_fn,
reason = "named helper called once by render(); kept separate for the dedup logic"
)]
fn merge_defs(client_root: &serde_json::Value, server_root: &serde_json::Value) -> serde_json::Value {
fn merge_defs(client_root: &serde_json::Value, server_root: &serde_json::Value) -> Result<serde_json::Value, Error> {
let mut merged = serde_json::Map::new();
for root in [client_root, server_root] {
if let Some(defs) = root.get("$defs").and_then(|val| val.as_object()) {
for (name, def) in defs {
// A `$defs` name shared by both schemas must resolve to the same definition; a mismatch means
// the client and server disagree on a shared type, which would silently pick one arbitrarily.
if let Some(previous) = merged.get(name) {
if previous != def {
return Err(Error::ConflictingDefs(name.clone()));
}
continue;
}
let _previous: Option<serde_json::Value> = merged.insert(name.clone(), def.clone());
}
}
Expand All @@ -90,7 +98,7 @@ fn merge_defs(client_root: &serde_json::Value, server_root: &serde_json::Value)
if !merged.is_empty() {
let _previous: Option<serde_json::Value> = root.insert("$defs".to_string(), serde_json::Value::Object(merged));
}
serde_json::Value::Object(root)
Ok(serde_json::Value::Object(root))
}

#[expect(
Expand Down
Loading